/* 
   Project: FisicaLab

   Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2020 Free Software Foundation

   Author: German A. Arias <germanandre@gmx.es>

   Created: 2008-09-10 18:56:00 -0600 by german
   
   Application Controller

   This application is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.
 
   This application is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.
 
   You should have received a copy of the GNU General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/

#import "ChalkboardView.h"
#import "RenaissanceController.h"
#import <math.h>
#import <Renaissance/Renaissance.h>

@implementation RenaissanceController

- (id) init
{
  if ((self = [super init]))
    {
      preferencesPanel = nil;
      propertiesWindow = nil;
    }
  return self;
}

- (void) applicationWillFinishLaunching: (NSNotification *)aNotification
{
  [NSBundle loadGSMarkupNamed: @"fisica" owner: self];

  // Hide the label use only for thermodynamics.
  [system setHidden: YES];
  // Select the SI system.
  [unitsSelector selectCellWithTag: 0];

  // Set delegate for TabViews
  [elements setDelegate: infoObj];
  [kinematicsTab setDelegate: infoObj];
  [staticsTab setDelegate: infoObj];
  [dynamicsTab setDelegate: infoObj];
  [heatTab setDelegate: infoObj];

  // Se the user frames for windows.
  [[elements window] setDelegate: self];
  [[elements window] setFrameUsingName: @"Palette"];
  [[chalkboard window] setDelegate: self];
  [[chalkboard window] setFrameUsingName: @"Chalkboard"];
}

- (void) applicationDidFinishLaunching: (NSNotification*)aNotification
{
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

  if (![defaults boolForKey: @"HasStartedBefore"])
    {
      NSTextField *url = [NSTextField new];
      NSButton *button = [NSButton new];
      [NSBundle loadGSMarkupNamed: @"firstLaunchPanel" owner: self];

      [url setBordered: NO];
      [url setBezeled: NO];
      [url setEditable: NO];
      [url setSelectable: YES];
      [url setStringValue: @"http://www.gnu.org/software/fisicalab/"];
      [url setFrame: NSMakeRect(235, 40, 250, 35)];

      [button setTitle: _(@"Don't show it again")];
      [button setButtonType: NSSwitchButton];
      [button setFrame: NSMakeRect(490, 5, 140, 30)];
      [button setImagePosition: NSImageRight];
      [button setTarget: self];
      [button setAction: @selector(notShowAgain:)];

      [[firstLaunchPanel contentView] addSubview: url];
      [[firstLaunchPanel contentView] addSubview: button];
      [firstLaunchPanel center];
      [firstLaunchPanel makeKeyAndOrderFront: self];

      [url release];
      [button release];
    }
}

- (void) showPrefPanel: (id)sender
{
  if (preferencesPanel == nil)
    {
      int width = 0, height = 0, size = 0;
      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
      [NSBundle loadGSMarkupNamed: @"preferences" owner: self];

      [preferencesPanel center];
      [preferencesPanel makeKeyAndOrderFront: self];
      
      width = [defaults integerForKey: @"ChalkboardWidth"];
      height = [defaults integerForKey: @"ChalkboardHeight"];
      size = [defaults integerForKey: @"NSToolTipsFontSize"];
      
      if ((width < 26) || (width > 100))
	{
	  width = 26;
	}
      
      if ( (height < 18) || (height > 100))
	{
	  height = 18;
	}

      if ( (size < 10) || (size > 20))
	{
	  size = 10;
	}

      [widthLabel setIntValue: width];
      [heightLabel setIntValue: height];
      [fontsizeLabel setIntValue: size];
      [widthStepper setIntValue: width];
      [heightStepper setIntValue: height];
      [fontsizeStepper setIntValue: size];
    }
  else
    {
      [preferencesPanel makeKeyAndOrderFront: self];
    }
}

- (void) showHelpPanel: (id)sender
{
  if (helpPanel == nil)
    {
      [NSBundle loadGSMarkupNamed: @"help" owner: self];
      [helpPanel makeKeyAndOrderFront: self];
    }
  else
    {
      [helpPanel makeKeyAndOrderFront: self];
    }
}

- (void) showPropertiesWindow: (id)sender
{
  if (propertiesWindow == nil)
    {
      [NSBundle loadGSMarkupNamed: @"properties" owner: self];
      [propertiesWindow makeKeyAndOrderFront: self];
    }
  else
    {
      [propertiesWindow makeKeyAndOrderFront: self];
    }
}

- (void) selectModule: (id)sender
{
  // Cancel any operation add/move element.
  [chalkboard controlCursor: self];
  
  /* If selected group is thermodynamics, show the label and hide units
     selector. If any other, hide the label and show the units selector.
     This because we only allow system SI in thermodynamics group. */
  if ([sender tag] == 3)
    {
      if ([system isHidden] == YES)
        {
          [system setHidden: NO];
          [unitsSelector setHidden: YES];
        }
    }
  else
    {
      if ([system isHidden] ==  NO)
        {
          [system setHidden: YES];
          [unitsSelector setHidden: NO];
        }
    }
  
  // Select the corresponding group of modules.
  [elements selectTabViewItemAtIndex: [sender tag]];
}

- (void) addToChalkboard: (id)sender
{
  CGFloat x, y, width, height, xRatio, yRatio;
  NSPoint loc;
  NSButton *button = [NSButton new];;
  NSEvent *e = [NSApp currentEvent];
  NSString *imageName;
  NSInteger elementTag;

  loc = [sender convertPoint: [e locationInWindow] fromView: nil];

  x = loc.x;
  y = loc.y;
  width = [sender frame].size.width;
  height = [sender frame].size.height;

  switch ([sender tag])
    {
	  // Statics Points: Forces.
	case 56:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    //yRatio = floor(cdCanvasUpdateYAxis((cdCanvas *)IupGetAttributeHandle(ih, "CANVAS"), &y)/(height/3));

	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"force_no";
		    elementTag = 58;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"force_o";
		    elementTag = 61;
		  }
		else
		  {
		    imageName = @"force_so";
		    elementTag = 57;
		  }
	      }
	    else if (xRatio == 1)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"force_n";
		    elementTag = 62;
		  }
		else if (yRatio == 1)
		  {
		    // Nothing to do.
		  }
		else
		  {
		    imageName = @"force_s";
		    elementTag = 63;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"force_ne";
		    elementTag = 56;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"force_e";
		    elementTag = 60;
		  }
		else
		  {
		    imageName = @"force_se";
		    elementTag = 59;
		  }
	      }
	  }
	  break;
	  // Statics Points: Frictions.
	case 64:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));

	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"friction_no";
		    elementTag = 66;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"friction_o";
		    elementTag = 69;
		  }
		else
		  {
		    imageName = @"friction_so";
		    elementTag = 65;
		  }
	      }
	    else if (xRatio == 1)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"friction_n";
		    elementTag = 70;
		  }
		else if (yRatio == 1)
		  {
		    // Nothing to do.
		  }
		else
		  {
		    imageName = @"friction_s";
		    elementTag = 71;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"friction_ne";
		    elementTag = 64;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"friction_e";
		    elementTag = 68;
		  }
		else
		  {
		    imageName = @"friction_se";
		    elementTag = 67;
		  }
	      }
	  }
	  break;
	  // Statics Points: Resultants.
	case 72:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (xRatio == 0)
	      {
		imageName = @"resultant";
		elementTag = 72;
	      }
	    else if (xRatio == 1)
	      {
		imageName = @"resultant_h";
		elementTag = 73;
	      }
	    else
	      {
		imageName = @"resultant_v";
		elementTag = 74;
	      }
	  }
	  break;
	  // Statics Points: Springs.
	case 75:
	  {
	    xRatio = floor(x/(width/4));
	    yRatio = floor(y/(height/4));
	    
	    if (xRatio == 0)
	      {
		imageName = @"spring_left";
		elementTag = 75;
	      }
	    else if (xRatio == 1)
	      {
		imageName = @"spring_right";
		elementTag = 76;
	      }
	    else if (xRatio == 2)
	      {
		imageName = @"spring_vertical";
		elementTag = 77;
	      }
	    else
	      {
		imageName = @"spring_horizontal";
		elementTag = 78;
	      }
	  }
	  break;
	  // Statics Rigid: Bodies.
	case 252:
	  {
	    xRatio = floor(x/(width/2));
	    yRatio = floor(y/(height/2));

	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"a_points";
		    elementTag = 276;
		  }
		else
		  {
		    // Nothing to do.
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"a_beam";
		    elementTag = 252;
		  }
		else
		  {
		    imageName = @"a_solid";
		    elementTag = 253;
		  }
	      }
	  }
	  break;
	  // Statics Rigid: Beam elements.
	case 255:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = (100*y)/height;
	    //NSLog(@"y: %d  height: %d ratio: %f", y, height, yRatio);
	    
	    if (xRatio == 0)
	      {
		if (yRatio <= 17)
		  {
		    imageName = @"element_beam_h_a";
		    elementTag = 301;
		  }
		else if (yRatio <= 46)
		  {
		    imageName = @"element_beam_v_a";
		    elementTag = 304;
		  }
		else if (yRatio <= 72)
		  {
		    imageName = @"element_beam_r_a";
		    elementTag = 307;
		  }
		else
		  {
		    imageName = @"element_beam_l_c";
		    elementTag = 310;
		  }
	      }
	    else if (xRatio == 1)
	      {
		if (yRatio <= 17)
		  {
		    imageName = @"element_beam_h_b";
		    elementTag = 302;
		  }
		else if (yRatio <= 46)
		  {
		    imageName = @"element_beam_v_b";
		    elementTag = 305;
		  }
		else if (yRatio <= 72)
		  {
		    imageName = @"element_beam_r_b";
		    elementTag = 308;
		  }
		else
		  {
		    imageName = @"element_beam_l_b";
		    elementTag = 311;
		  }
	      }
	    else
	      {
		if (yRatio <= 17)
		  {
		    imageName = @"element_beam_h_c";
		    elementTag = 303;
		  }
		else if (yRatio <= 46)
		  {
		    imageName = @"element_beam_v_c";
		    elementTag = 306;
		  }
		else if (yRatio <= 72)
		  {
		    imageName = @"element_beam_r_c";
		    elementTag = 309;
		  }
		else
		  {
		    imageName = @"element_beam_l_a";
		    elementTag = 312;
		  }
	      }
	  }
	  break;
	  // Statics Rigid: Solid elements.
	case 500:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (yRatio == 0)
	      {
		if (xRatio == 0)
		  {
		    imageName = @"element_solid_r_a";
		    elementTag = 401;
		  }
		else if (xRatio == 1)
		  {
		    imageName = @"element_solid_r_b";
		    elementTag = 404;
		  }
		else
		  {
		    imageName = @"element_solid_r_c";
		    elementTag = 407;
		  }
	      }
	    else if (yRatio == 1)
	      {
		if (xRatio == 0)
		  {
		    imageName = @"element_solid_r_d";
		    elementTag = 402;
		  }
		else if (xRatio == 1)
		  {
		    imageName = @"element_solid_r_e";
		    elementTag = 405;
		  }
		else
		  {
		    imageName = @"element_solid_r_f";
		    elementTag = 408;
		  }
	      }
	    else
	      {
		if (xRatio == 0)
		  {
		    imageName = @"element_solid_r_g";
		    elementTag = 403;
		  }
		else if (xRatio == 1)
		  {
		    imageName = @"element_solid_r_h";
		    elementTag = 406;
		  }
		else
		  {
		    imageName = @"element_solid_r_i";
		    elementTag = 409;
		  }
	      }
	  }
	  break;
	case 501:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (yRatio == 0)
	      {
		if (xRatio == 0)
		  {
		    imageName = @"element_solid_d_a";
		    elementTag = 411;
		  }
		else if (xRatio == 1)
		  {
		    imageName = @"element_solid_d_b";
		    elementTag = 414;
		  }
		else
		  {
		    imageName = @"element_solid_d_c";
		    elementTag = 417;
		  }
	      }
	    else if (yRatio == 1)
	      {
		if (xRatio == 0)
		  {
		    imageName = @"element_solid_d_d";
		    elementTag = 412;
		  }
		else if (xRatio == 1)
		  {
		    imageName = @"element_solid_d_e";
		    elementTag = 415;
		  }
		else
		  {
		    imageName = @"element_solid_d_f";
		    elementTag = 418;
		  }
	      }
	    else
	      {
		if (xRatio == 0)
		  {
		    imageName = @"element_solid_d_g";
		    elementTag = 413;
		  }
		else if (xRatio == 1)
		  {
		    imageName = @"element_solid_d_h";
		    elementTag = 416;
		  }
		else
		  {
		    imageName = @"element_solid_d_i";
		    elementTag = 419;
		  }
	      }
	  }
	  break;
	case 502:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (yRatio == 0)
	      {
		if (xRatio == 0)
		  {
		    imageName = @"element_solid_c_a";
		    elementTag = 421;
		  }
		else if (xRatio == 1)
		  {
		    imageName = @"element_solid_c_b";
		    elementTag = 424;
		  }
		else
		  {
		    imageName = @"element_solid_c_c";
		    elementTag = 427;
		  }
	      }
	    else if (yRatio == 1)
	      {
		if (xRatio == 0)
		  {
		    imageName = @"element_solid_c_d";
		    elementTag = 422;
		  }
		else if (xRatio == 1)
		  {
		    imageName = @"element_solid_c_e";
		    elementTag = 425;
		  }
		else
		  {
		    imageName = @"element_solid_c_f";
		    elementTag = 428;
		  }
	      }
	    else
	      {
		if (xRatio == 0)
		  {
		    imageName = @"element_solid_c_g";
		    elementTag = 423;
		  }
		else if (xRatio == 1)
		  {
		    imageName = @"element_solid_c_h";
		    elementTag = 426;
		  }
		else
		  {
		    imageName = @"element_solid_c_i";
		    elementTag = 427;
		  }
	      }
	  }
	  break;
	  // Statics Rigid: Forces.
	case 257:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"force_no";
		    elementTag = 259;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"force_o";
		    elementTag = 262;
		  }
		else
		  {
		    imageName = @"force_so";
		    elementTag = 258;
		  }
	      }
	    else if (xRatio == 1)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"force_n";
		    elementTag = 263;
		  }
		else if (yRatio == 1)
		  {
		    // Nothing to do.
		  }
		else
		  {
		    imageName = @"force_s";
		    elementTag = 264;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"force_ne";
		    elementTag = 257;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"force_e";
		    elementTag = 261;
		  }
		else
		  {
		    imageName = @"force_se";
		    elementTag = 260;
		  }
	      }
	  }
	  break;
	  // Statics Rigid: Frictions.
	case 265:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"friction_no";
		    elementTag = 267;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"friction_o";
		    elementTag = 270;
		  }
		else
		  {
		    imageName = @"friction_so";
		    elementTag = 266;
		  }
	      }
	    else if (xRatio == 1)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"friction_n";
		    elementTag = 271;
		  }
		else if (yRatio == 1)
		  {
		    // Nothing to do.
		  }
		else
		  {
		    imageName = @"friction_s";
		    elementTag = 272;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"friction_ne";
		    elementTag = 265;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"friction_e";
		    elementTag = 269;
		  }
		else
		  {
		    imageName = @"friction_se";
		    elementTag = 268;
		  }
	      }
	  }
	  break;
	  // Statics Rigid: Resultants.
	case 273:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (xRatio == 0)
	      {
		imageName = @"resultant_moment";
		elementTag = 273;
	      }
	    else if (xRatio == 1)
	      {
		imageName = @"resultant_moment_h";
		elementTag = 274;
	      }
	    else
	      {
		imageName = @"resultant_moment_v";
		elementTag = 275;
	      }
	  }
	  break;
	  // Statics Rigid: Beam 2F.
	case 277:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"beam_two_forces_no";
		    elementTag = 279;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"beam_two_forces_o";
		    elementTag = 282;
		  }
		else
		  {
		    imageName = @"beam_two_forces_so";
		    elementTag = 278;
		  }
	      }
	    else if (xRatio == 1)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"beam_two_forces_n";
		    elementTag = 283;
		  }
		else if (yRatio == 1)
		  {
		    // Nothing to do.
		  }
		else
		  {
		    imageName = @"beam_two_forces_s";
		    elementTag = 284;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"beam_two_forces_ne";
		    elementTag = 277;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"beam_two_forces_e";
		    elementTag = 281;
		  }
		else
		  {
		    imageName = @"beam_two_forces_se";
		    elementTag = 280;
		  }
	      }
	  }
	  break;
	  // Statics Rigid: Beams of truss.
	case 285:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"beam_truss_no";
		    elementTag = 287;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"beam_truss_o";
		    elementTag = 290;
		  }
		else
		  {
		    imageName = @"beam_truss_so";
		    elementTag = 286;
		  }
	      }
	    else if (xRatio == 1)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"beam_truss_n";
		    elementTag = 291;
		  }
		else if (yRatio == 1)
		  {
		    // Nothing to do.
		  }
		else
		  {
		    imageName = @"beam_truss_s";
		    elementTag = 292;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"beam_truss_ne";
		    elementTag = 285;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"beam_truss_e";
		    elementTag = 289;
		  }
		else
		  {
		    imageName = @"beam_truss_se";
		    elementTag = 288;
		  }
	      }
	  }
	  break;
	  // Dynamics of points
	  // Mobiles
	case 101:
	  {
	    xRatio = floor(x/(width/2));
	    yRatio = floor(y/(height/2));

	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"mobile_y";
		    elementTag = 103;
		  }
		else
		  {
		    // Nothing to do.
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"mobile";
		    elementTag = 101;
		  }
		else
		  {
		    imageName = @"mobile_x";
		    elementTag = 102;
		  }
	      }
	  }
	  break;
	  // Blocks
	case 104:
	  {
	    xRatio = floor(x/(width/2));
	    yRatio = floor(y/(height/2));

	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"block_left";
		    elementTag = 106;
		  }
		else
		  {
		    imageName = @"block_vertical";
		    elementTag = 104;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"block_right";
		    elementTag = 107;
		  }
		else
		  {
		    imageName = @"block_horizontal";
		    elementTag = 105;
		  }
	      }
	  }
	  break;
	case 139:
	  {
	    xRatio = floor(x/(width/2));
	    yRatio = floor(y/(height/2));

	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"energy";
		    elementTag = 139;
		  }
		else
		  {
		    // Nothing to do.
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    // Nothing to do.
		  }
		else
		  {
		    imageName = @"momentum_linear";
		    elementTag = 140;
		  }
	      }
	  }
	  break;
	  // Dynamics Points: Springs.
	case 133:
	  {
	    xRatio = floor(x/(width/4));
	    yRatio = floor(y/(height/4));

	    if (xRatio == 0)
	      {
		imageName = @"spring_left";
		elementTag = 133;
	      }
	    else if (xRatio == 1)
	      {
		imageName = @"spring_right";
		elementTag = 134;
	      }
	    else if (xRatio == 2)
	      {
		imageName = @"spring_vertical";
		elementTag = 135;
	      }
	    else
	      {
		imageName = @"spring_horizontal";
		elementTag = 136;
	      }
	  }
	  break;
	  // Dynamics Points: Forces.
	case 109:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"force_no";
		    elementTag = 111;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"force_o";
		    elementTag = 114;
		  }
		else
		  {
		    imageName = @"force_so";
		    elementTag = 110;
		  }
	      }
	    else if (xRatio == 1)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"force_n";
		    elementTag = 115;
		  }
		else if (yRatio == 1)
		  {
		    // Nothing to do.
		  }
		else
		  {
		    imageName = @"force_s";
		    elementTag = 116;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"force_ne";
		    elementTag = 109;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"force_e";
		    elementTag = 113;
		  }
		else
		  {
		    imageName = @"force_se";
		    elementTag = 112;
		  }
	      }
	  }
	  break;
	  // Dynamics Points: Frictions.
	case 117:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"friction_no";
		    elementTag = 119;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"friction_o";
		    elementTag = 122;
		  }
		else
		  {
		    imageName = @"friction_so";
		    elementTag = 118;
		  }
	      }
	    else if (xRatio == 1)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"friction_n";
		    elementTag = 123;
		  }
		else if (yRatio == 1)
		  {
		    // Nothing to do.
		  }
		else
		  {
		    imageName = @"friction_s";
		    elementTag = 124;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"friction_ne";
		    elementTag = 117;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"friction_e";
		    elementTag = 121;
		  }
		else
		  {
		    imageName = @"friction_se";
		    elementTag = 120;
		  }
	      }
	  }
	  break;
	  // Dynamics Points: Contacts.
	case 125:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"contact_no";
		    elementTag = 127;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"contact_o";
		    elementTag = 130;
		  }
		else
		  {
		    imageName = @"contact_so";
		    elementTag = 126;
		  }
	      }
	    else if (xRatio == 1)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"contact_n";
		    elementTag = 131;
		  }
		else if (yRatio == 1)
		  {
		    // Nothing to do.
		  }
		else
		  {
		    imageName = @"contact_s";
		    elementTag = 132;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"contact_ne";
		    elementTag = 125;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"contact_e";
		    elementTag = 129;
		  }
		else
		  {
		    imageName = @"contact_se";
		    elementTag = 128;
		  }
	      }
	  }
	  break;
	  // Dynamics Circular: Springs.
	case 317:
	  {
	    xRatio = floor(x/(width/4));
	    yRatio = floor(y/(height/4));

	    if (xRatio == 0)
	      {
		imageName = @"spring_left";
		elementTag = 317;
	      }
	    else if (xRatio == 1)
	      {
		imageName = @"spring_right";
		elementTag = 318;
	      }
	    else if (xRatio == 2)
	      {
		imageName = @"spring_vertical";
		elementTag = 319;
	      }
	    else
	      {
		imageName = @"spring_horizontal";
		elementTag = 320;
	      }
	  }
	  break;
	  // Dynamics Circular: Forces.
	case 321:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"force_no";
		    elementTag = 321;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"force_o";
		    elementTag = 328;
		  }
		else
		  {
		    imageName = @"force_so";
		    elementTag = 324;
		  }
	      }
	    else if (xRatio == 1)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"force_n";
		    elementTag = 325;
		  }
		else if (yRatio == 1)
		  {
		    // Nothing to do.
		  }
		else
		  {
		    imageName = @"force_s";
		    elementTag = 326;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"force_ne";
		    elementTag = 323;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"force_e";
		    elementTag = 327;
		  }
		else
		  {
		    imageName = @"force_se";
		    elementTag = 322;
		  }
	      }
	  }
	  break;
	  // Dynamics Circular: Frictions.
	case 329:
	  {
	    xRatio = floor(x/(width/3));
	    yRatio = floor(y/(height/3));
	    
	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"friction_no";
		    elementTag = 330;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"friction_o";
		    elementTag = 329;
		  }
		else
		  {
		    imageName = @"friction_so";
		    elementTag = 341;
		  }
	      }
	    else if (xRatio == 1)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"friction_n";
		    elementTag = 331;
		  }
		else if (yRatio == 1)
		  {
		    // Nothing to do.
		  }
		else
		  {
		    // Nothing to do.
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"friction_ne";
		    elementTag = 332;
		  }
		else if (yRatio == 1)
		  {
		    imageName = @"friction_e";
		    elementTag = 333;
		  }
		else
		  {
		    imageName = @"friction_se";
		    elementTag = 342;
		  }
	      }
	  }
	  break;
	  // Calorimetry
	  // Expansion
	case 600:
	  {
	    xRatio = floor(x/(width/2));
	    yRatio = floor(y/(height/2));

	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"expansion_linear";
		    elementTag = 157;
		  }
		else
		  {
		    // Nothing to do.
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"expansion_superficial";
		    elementTag = 158;
		  }
		else
		  {
		    imageName = @"expansion_volumetric";
		    elementTag = 159;
		  }
	      }
	  }
	  break;
	  // Change state
	case 601:
	  {
	    xRatio = floor(x/(width/2));
	    yRatio = floor(y/(height/2));

	    if (xRatio == 0)
	      {
		if (yRatio == 0)
		  {
		    imageName = @"change_state_solid_liquid";
		    elementTag = 160;
		  }
		else
		  {
		    // Nothing to do.
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"process";
		    elementTag = 162;
		  }
		else
		  {
		    imageName = @"change_state_liquid_gas";
		    elementTag = 161;
		  }
	      }
	  }
	  break;
    }

  [button setImage: [NSImage imageNamed: imageName]];
  [button setTag: elementTag];
  [chalkboard addObject: button];
}

- (void) windowWillClose: (NSNotification *)aNotification
{
  id window = [aNotification object];
  
  if (window == [chalkboard window])
    {
      [window saveFrameUsingName: @"Chalkboard"];
    }
  
  if (window == [elements window])
    {
      [window saveFrameUsingName: @"Palette"];
    }
}

// Preferences
- (void) changeChalkboardWidth: (id)sender
{
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  [defaults setInteger: [sender intValue] forKey: @"ChalkboardWidth"];
  [widthLabel setIntValue: [sender intValue]];
}

- (void) changeChalkboardHeight: (id)sender
{
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  [defaults setInteger: [sender intValue] forKey: @"ChalkboardHeight"];
  [heightLabel setIntValue: [sender intValue]];
}

- (void) changeFontsizeTooltips: (id)sender
{
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  [defaults setInteger: [sender intValue] forKey: @"NSToolTipsFontSize"];
  [fontsizeLabel setIntValue: [sender intValue]];
}

- (void) restoreDefaults: (id)sender
{
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  [defaults removeObjectForKey: @"ChalkboardWidth"];
  [defaults removeObjectForKey: @"ChalkboardHeight"];
  [defaults removeObjectForKey: @"NSToolTipsFontSize"];

  [widthLabel setIntValue: 26];
  [heightLabel setIntValue: 18];
  [fontsizeLabel setIntValue: 10];
  [widthStepper setIntValue: 26];
  [heightStepper setIntValue: 18];
  [fontsizeStepper setIntValue: 10];
}

// First launch panel
- (void) notShowAgain: (id)sender
{
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  [defaults setBool: YES forKey: @"HasStartedBefore"];
}

@end
