/* 
   Copyright (C) 2017, 2018, 2019, 2020, 2023 German A. Arias

   This file is part of FísicaLab application

   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 "IupInterface.h"
#import "FLSolverWithCells.h"
#import "FLProcessMathematics.h"
#import <iup/iup.h>
#import <iup/iupcontrols.h>
#import <iup/iupim.h>
#import <cd/cd.h>
#import <iup/iup_config.h>

id owner;
int count, unitsSystem, width, height, clickedCell;
BOOL newObject, moveObject;
Ihandle *modbox, *dlg, *matrix, *mline, *toggle, *selectedCell, *chalkBoard,
  *image, *config;
NSString *objects;
NSNumber *numberId, *objectCode;
NSMutableDictionary *objectsList, *conversionDictionary;
FLProcessMathematics *mathProcess;

void updateMatrix()
{
  if (numberId != nil && [numberId intValue] > 0)
    {
      int x;
      NSString *d1, *d2;
      NSMutableDictionary *object = [objectsList objectForKey: numberId];
      NSMutableArray *listTitles = [object objectForKey: @"Titles"];
      NSMutableArray *listData = [object objectForKey: @"Data"];

      IupSetAttribute(matrix, "NUMLIN",
		      [[[NSNumber numberWithUnsignedInteger: [listTitles count]]
			 stringValue] cString]);

      for (x = 1; x <= [listTitles count]; x++)
	{
	  
	  d1 = [[listTitles objectAtIndex: x - 1] description];
	  d2 = [listData objectAtIndex: x - 1];
	  
	  IupSetAttributeId2(matrix, "", x, 1, [d1 cString]);
	  IupSetAttributeId2(matrix, "", x, 2, [d2 cString]);
	}
    }
  else
    {
      IupSetAttribute(matrix, "NUMLIN", "1");
      IupSetAttributeId2(matrix, "", 1, 1, "");
      IupSetAttributeId2(matrix, "", 1, 2, "");
    }

  IupSetAttribute(matrix, "REDRAW", "ALL");
}

void updateSelectedCell( Ihandle *wgt )
{
  if (selectedCell != NULL)
    {
      IupSetAttribute(selectedCell, "BGCOLOR", "0 0 0");
      IupResetAttribute(selectedCell, "HLCOLOR");
      IupRedraw(selectedCell, 1);
    }
  
  IupSetAttribute(wgt, "BGCOLOR", "50 50 50");
  IupSetAttribute(wgt, "HLCOLOR", "230 230 0");
  IupRedraw(wgt, 1);
  selectedCell = wgt;
}

void cleanCell( Ihandle *wgt )
{
  IupSetAttribute(wgt, "BGCOLOR", "0 0 0");
  IupResetAttribute(wgt, "HLCOLOR");
  IupRedraw(wgt, 1);

  if (selectedCell == wgt)
    {
      selectedCell = NULL;
    }
}

int dropdown_cb( Ihandle *wgt )
{
  Ihandle *r;
  int v = [[NSString stringWithCString: IupGetAttribute(wgt, "VALUE")]
	    intValue];
  NSString *status;

  switch (v)
    {
    case 1:
      IupSetAttribute(modbox, "VALUE", "FLKinematics");
      break;
    case 2:
      IupSetAttribute(modbox, "VALUE", "FLKinematicsCircularMotion");
      break;
    case 3:
      IupSetAttribute(modbox, "VALUE", "FLStatics");
      break;
    case 4:
      IupSetAttribute(modbox, "VALUE", "FLStaticsRigidBodies");
      break;
    case 5:
      IupSetAttribute(modbox, "VALUE", "FLDynamics");
      break;
    case 6:
      IupSetAttribute(modbox, "VALUE", "FLDynamicsCircularMotion");
      break;
    case 7:
      IupSetAttribute(modbox, "VALUE", "FLCalorimetry");
      break;
    case 8:
      IupSetAttribute(modbox, "VALUE", "FLThermodynamics");
      break;
    default:
      IupSetAttribute(modbox, "VALUE", "FLKinematics");
    }

  r = IupGetDialogChild(wgt, "UNITS_RADIO");

  status = [NSString stringWithCString:
		       IupGetAttribute(r, "VISIBLE")];

  if ( (v == 7 || v == 8) && [status isEqualToString: @"YES"] )
    {
      IupSetAttribute(r, "VISIBLE", "NO");
      IupRedraw(r, 1);
    }
  else if ( v != 7 && v != 8 && [status isEqualToString: @"NO"] )
    {
      IupSetAttribute(r, "VISIBLE", "YES");
      IupRedraw(r, 1);
    }
  
  return IUP_DEFAULT;
}

int clickCell_cb( Ihandle *wgt )
{
  NSString *controlKey, *shiftKey;
  Ihandle *img = IupGetAttributeHandle(wgt, "IMAGE");

  controlKey = [NSString stringWithCString:
			   IupGetGlobal("CONTROLKEY")];
  shiftKey = [NSString stringWithCString:
			 IupGetGlobal("SHIFTKEY")];

  // Add the new element at clicked cell.
  if (newObject && img == NULL)
    {
      IupSetAttributeHandle(wgt, "IMAGE", image);
      updateSelectedCell(wgt);
      IupSetAttribute(dlg, "CURSOR", "ARROW");
      //[information addObject: sender];
      count += 1;
      IupSetInt(wgt, "TAG", count);
      newObject = NO;
      image = NULL;

      NSString *imageName;
      NSArray *moduleData;
      NSArray *titleList = nil, *unitsList = nil;
      NSMutableArray *dataList = nil;
      NSMutableArray *valueList = [NSMutableArray array];
      NSMutableDictionary *data;

      NSNumber *type;
      //[dataViewer deselectRow: [dataViewer selectedRow]];
      //[dataViewer setMenu: nil];
  
      // Get the corresponding data.
      moduleData =
	[NSClassFromString(objects) dataForElementWithTag: [objectCode intValue]
						forSystem: unitsSystem];

      titleList = [moduleData objectAtIndex: 0];
      dataList = [moduleData objectAtIndex: 1];
      unitsList = [moduleData objectAtIndex: 2];
      type = [moduleData objectAtIndex: 3];
      imageName = [moduleData objectAtIndex: 4];

      if ([titleList count] != [dataList count] ||
	  [dataList count] != [unitsList count])
	{
	  NSLog(@"Error in number of entries.");
	}
      else
	{
	  data = [NSMutableDictionary dictionaryWithObjectsAndKeys: type, @"Type",
				      titleList, @"Titles",
				      dataList, @"Data",
				      unitsList, @"Dimensions",
				      valueList, @"Values",
				      imageName, @"Image", nil];
	  ASSIGN(numberId, [NSNumber numberWithInt: count]);
	  [objectsList setObject: data forKey: numberId];
	  IupSetInt(wgt, "TAG", [numberId intValue]);
	  IupSetAttribute(wgt, "TIP", [[owner dataOfObject: numberId] cString]);
	  updateMatrix();
	}
    }
  // Add the moved element at clicked cell.
  else if (moveObject && img == NULL)
    {
      IupSetAttributeHandle(wgt, "IMAGE", image);
      updateSelectedCell(wgt);
      IupSetAttribute(dlg, "CURSOR", "ARROW");
      IupSetInt(wgt, "TAG", [objectCode intValue]);
      IupSetAttribute(wgt, "TIP", [[owner dataOfObject: numberId] cString]);
      moveObject = NO;
      image = NULL;
    }
  // Begins a move operation for the element at clicked cell.
  else if ([controlKey isEqualToString: @"ON"] && (img != NULL)
	   && (image == NULL))
    {
      image = IupGetAttributeHandle(wgt, "IMAGE");
      objectCode = [NSNumber numberWithInt:
			       IupGetInt(wgt, "TAG")];
      IupSetAttribute(wgt, "IMAGE", NULL);
      IupSetInt(wgt, "TAG", 0);
      IupSetAttribute(wgt, "TIP", NULL);
      cleanCell(wgt);
      IupSetAttribute(dlg, "CURSOR", "HAND");
      moveObject = YES;
    }
  // Delete the element at clicked cell.
  else if ([shiftKey isEqualToString: @"ON"] && (img != NULL)
	   && (image == NULL))
    {
      updateSelectedCell(wgt);
      IupSetAttribute(wgt, "IMAGE", NULL);
      //[information deleteObject: [sender tag]];
      [objectsList removeObjectForKey: [NSNumber numberWithInt:
						   IupGetInt(wgt, "TAG")]];
      IupSetInt(wgt, "TAG", 0);
      IupSetAttribute(wgt, "TIP", NULL);
      img = NULL;
      cleanCell(wgt);
      count -= 1;
      ASSIGN(numberId, nil);
      updateMatrix();

      if (count == 0)
	{
	  objects = nil;
	}
      
      //DESTROY(selectedCell);
      //[self setNeedsDisplay: YES];
    }

  // Then update the table with the info of the element at clicked cell.
  if (!newObject && !moveObject && (img != NULL))
    {
      //[dataViewer deselectRow: [dataViewer selectedRow]];
      ASSIGN(numberId, [NSNumber numberWithInt:	IupGetInt(wgt, "TAG")]);
      //[dataViewer setMenu: nil];
      updateMatrix();
      updateSelectedCell(wgt);
      //ASSIGN(selectedCell, [NSBezierPath bezierPathWithRect: [sender frame]]);
      //[self setNeedsDisplay: YES];
    }

  return IUP_DEFAULT;
}

int clickElement_cb( Ihandle *wgt )
{
  BOOL decision = NO;
  NSString *selected = [NSString stringWithCString:
				   IupGetAttribute(modbox, "VALUE")];
  
  if (objects == nil)
    {
      ASSIGN(objects, selected);
      decision = YES;
      //NSLog(@"%@", objects);
    }
  else
    {
      if ([objects isEqualToString: selected])
	{
          decision = YES;
	} 
      else
	{
          decision = NO;
	}
    }

  if (decision)
    {
      image = IupGetAttributeHandle(wgt, "IMAGE");
      objectCode = [NSNumber numberWithInt:
			       IupGetInt(wgt, "TAG")];
      newObject = YES;
      IupSetAttribute(dlg, "CURSOR", "HAND");
    }
  
  return IUP_DEFAULT;
}

int clickImage_cb( Ihandle* ih, int button, int pressed, int x, int y, char* status )
{
  int width, height, tag, elementTag;
  double xRatio, yRatio;
  NSString *size, *imageName;
  BOOL decision = NO;
  NSString *selected = [NSString stringWithCString:
				   IupGetAttribute(modbox, "VALUE")];
  NSBundle *mb = [NSBundle mainBundle];

  if (objects == nil)
    {
      ASSIGN(objects, selected);
      decision = YES;
      //NSLog(@"%@", objects);
    }
  else
    {
      if ([objects isEqualToString: selected])
	{
          decision = YES;
	} 
      else
	{
          decision = NO;
	}
    }

  if (decision)
    {
      tag = IupGetInt(ih, "TAG");
      size = [NSString stringWithCString: IupGetAttribute(ih, "RASTERSIZE")];

      width = [[[size componentsSeparatedByString: @"x"] firstObject] intValue];
      height = [[[size componentsSeparatedByString: @"x"] lastObject] intValue];

      switch (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)
		  {
		    return IUP_DEFAULT;
		  }
		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)
		  {
		    return IUP_DEFAULT;
		  }
		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
		  {
		    return IUP_DEFAULT;
		  }
	      }
	    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)
		  {
		    return IUP_DEFAULT;
		  }
		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)
		  {
		    return IUP_DEFAULT;
		  }
		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)
		  {
		    return IUP_DEFAULT;
		  }
		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)
		  {
		    return IUP_DEFAULT;
		  }
		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
		  {
		    return IUP_DEFAULT;
		  }
	      }
	    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
		  {
		    return IUP_DEFAULT;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    return IUP_DEFAULT;
		  }
		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)
		  {
		    return IUP_DEFAULT;
		  }
		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)
		  {
		    return IUP_DEFAULT;
		  }
		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)
		  {
		    return IUP_DEFAULT;
		  }
		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)
		  {
		    return IUP_DEFAULT;
		  }
		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)
		  {
		    return IUP_DEFAULT;
		  }
		else
		  {
		    return IUP_DEFAULT;
		  }
	      }
	    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
		  {
		    return IUP_DEFAULT;
		  }
	      }
	    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
		  {
		    return IUP_DEFAULT;
		  }
	      }
	    else
	      {
		if (yRatio == 0)
		  {
		    imageName = @"process";
		    elementTag = 162;
		  }
		else
		  {
		    imageName = @"change_state_liquid_gas";
		    elementTag = 161;
		  }
	      }
	  }
	  break;
	}
      
      image = IupLoadImage([[mb pathForResource: imageName ofType: @"tif"] cString]);
      objectCode = [NSNumber numberWithInt: elementTag];
      newObject = YES;
      IupSetAttribute(dlg, "CURSOR", "HAND");
    }

  return IUP_DEFAULT;
}

// Iup matrix (Table)

int editionTable_cb(Ihandle *ih, int lin, int col, int mode, int update)
{
  if (col == 1)
    return IUP_IGNORE;
  else
    return IUP_DEFAULT;
}

int actionTable_cb(Ihandle *ih, int key, int lin, int col, int edition, char* value)
{
  return IUP_DEFAULT;
}

int editTable_cb(Ihandle *ih, int lin, int col, char* newval)
{
  NSRange range;
  NSString *factor = nil;
  NSString *entry = [NSString stringWithCString: newval];      
  NSMutableDictionary *object = [objectsList objectForKey: numberId];
  NSMutableArray *list = [object objectForKey: @"Data"];

  range = [entry rangeOfString: @"@"];
  if (range.length > 0)
    {
      factor = [entry substringFromIndex: range.location];
      entry = [[entry substringToIndex: range.location]
		stringByTrimmingSpaces];
    }

  if ([[[[object objectForKey: @"Titles"] objectAtIndex: lin - 1]
	 description] hasPrefix: @"ang"])
    {
      entry = [mathProcess processAngleEntry: entry];
    }
  else
    {
      entry = [mathProcess processEntry: entry];
    }
  
  if (factor != nil)
    {
      entry = [NSString stringWithFormat: @"%@ %@",
			entry,
			factor];
    }

  [list replaceObjectAtIndex: lin - 1
		  withObject: entry];

  updateMatrix();

  if (selectedCell != NULL)
    {
      IupSetAttribute(selectedCell, "TIP",
		      [[owner dataOfObject: numberId] cString]);
    }
  
  return IUP_DEFAULT;
}

// Select units

int selectUnits_cb(Ihandle* ih)
{
  NSString *selected = [NSString stringWithCString:
				   IupGetAttribute(ih, "TITLE")];

  if ([selected isEqualToString: @"SI"])
    {
      unitsSystem = 0;
    }
  else
    {
      unitsSystem = 1;
    }

  return IUP_DEFAULT;
}

// Buttons

int solve_cb(Ihandle* ih)
{
  id flModule;
  NSString *state = [NSString stringWithCString:
				IupGetAttribute(toggle, "VALUE")];

  if ([state isEqualToString: @"ON"])
    {
      IupSetAttribute(mline, "VALUE", "");
    }

  /* Instantiate the class for the problem and pass all the
     information to solve it. */
  flModule = [NSClassFromString(objects) new];
  [flModule setSystem: unitsSystem];
  [flModule setConversions: conversionDictionary];
  [flModule setViewer: owner];

  // If the module use cells, pass the corresponding information.
  if ([flModule isKindOfClass: [FLSolverWithCells class]])
    {
      [flModule setCells: [owner cellsInfo]];
      [flModule withChalkboardWidth: width
			     height: height];
    }
  
  [flModule solveProblemWithData: objectsList];
  [flModule release];
  
  return IUP_DEFAULT;
}

int clean_cb(Ihandle* ih)
{
  int x;
  Ihandle *a_cell;
  
  for (x = 0; x < width*height - 1; x++)
    {
      a_cell = IupGetChild(chalkBoard, x);
      
      IupSetAttribute(a_cell, "BGCOLOR", "0 0 0");
      IupResetAttribute(a_cell, "HLCOLOR");
      IupSetAttribute(a_cell, "IMAGE", NULL);
      IupSetAttribute(a_cell, "TIP", NULL);
      [objectsList removeObjectForKey: [NSNumber numberWithInt:
						   IupGetInt(a_cell, "TAG")]];
      IupSetInt(a_cell, "TAG", 0);
    }

  count = 0;
  [objectsList removeAllObjects];
  ASSIGN(objects, nil);
  ASSIGN(numberId, nil);
  selectedCell = NULL;
  updateMatrix();
  IupRedraw(chalkBoard, 1);

  return IUP_DEFAULT;
}

int insertFactor_cb(Ihandle *ih)
{
  if (clickedCell > -1)
    {
      NSString *val, *newValue;
      NSArray *text;
      NSMutableArray *list;

      list = [[objectsList objectForKey: numberId]
      			           objectForKey: @"Data"];

      val = [[list objectAtIndex: clickedCell - 1] description];
      text = [val componentsSeparatedByString: @"@"];
      
      newValue = [[text objectAtIndex: 0] stringByTrimmingSpaces];
      newValue = [newValue stringByAppendingString: @" @ "];
      newValue = [newValue stringByAppendingString:
		       [NSString stringWithCString:
				   IupGetAttribute(ih, "TITLE")]];
      //IupSetAttributeId2(matrix, "", 2, clickedCell, [newValue cString]);
      [list replaceObjectAtIndex: clickedCell - 1 withObject: newValue];
      
      clickedCell = -1;
      updateMatrix();
      IupSetFocus(dlg);
    }
  
  return IUP_CONTINUE;
}

int clickTable_cb(Ihandle *ih, int lin, int col, char *status)
{
  // Set a transient menu with the selected conversion factors.
  int r;
  int i = iup_isbutton3(status);
    
  if (i == 1 && lin > -1)
    {
      id factor;
      Ihandle *item, *factorsMenu;
      NSEnumerator *conv = nil;
      NSArray *units;

      clickedCell = lin;
      
      units = [[objectsList objectForKey: numberId]
		objectForKey: @"Dimensions"];
      
      // Select the appropriate list of conversion factors.
      conv =
        [[[conversionDictionary objectForKey: [units objectAtIndex: lin - 1]]
	   objectAtIndex: unitsSystem] keyEnumerator];
      
      factorsMenu = IupMenu(NULL);
      
      while ((factor = [conv nextObject]))
	{
	  if ([[factor description] isEqualToString: @"degrees"])
	    {
	      item = IupItem([_(@"degrees") cString], NULL);
	    }
	  else
	    {
	      item = IupItem([[factor description] cString], NULL);
	    }

	  IupSetAttribute(item, "HIDEMARK", "YES");
	  IupSetCallback(item, "ACTION", (Icallback)insertFactor_cb);
	  IupAppend(factorsMenu, item);
	}
      
      r = IupPopup(factorsMenu, IUP_MOUSEPOS, IUP_MOUSEPOS);
      IupDestroy(factorsMenu);

      if (r == IUP_ERROR)
	{
	}
    }

  return IUP_CONTINUE;
}

// Menu

int about_cb(Ihandle *ih)
{
  Ihandle* dlg = IupMessageDlg();

  IupSetAttribute(dlg, "PARENTDIALOG", "FisicaLab");
  IupSetAttribute(dlg, "DIALOGTYPE", "MESSAGE");
  IupSetAttribute(dlg, "TITLE", "GNU FisicaLab");
  IupSetAttribute(dlg, "BUTTONS", "OK");
  IupSetAttribute(dlg, "VALUE", "GNU FisicaLab 0.4.0 (October 2023) \nA physics solver \nReleased under GPLv3+ \nAuthor: Germán Arias \nWebsite: www.gnu.org/software/fisicalab/ ");
 
  IupPopup(dlg, IUP_CURRENT, IUP_CURRENT);

  IupDestroy(dlg); 

  return IUP_CONTINUE;
}

int param_action(Ihandle* ih, int param_index, void* user_data)
{
  int r = 1;
  Ihandle* param = (Ihandle*)IupGetAttributeId(ih, "PARAM", param_index);
  int value = IupGetInt(param, "VALUE");

  if (param_index == 0)
    {
      if ( (value < 26) || (value > 100) )
	{
	  r = 0;
	}
      else
	{
	  IupConfigSetVariableInt(config, "MainWindow", "widthChalkBoard", value);
	}
    }
  else if (param_index == 1)
    {
      if ( (value < 18) || (value > 100) )
	{
	  r = 0;
	}
      else
	{
	  IupConfigSetVariableInt(config, "MainWindow", "heightChalkBoard", value); 
	}
    }
  else if (param_index == 2)
    {
      if (value == 0)
	{
	  IupSetLanguage("ENGLISH");
	  IupConfigSetVariableStr(config, "MainWindow", "Language", "ENGLISH");
	}
      else
	{
	  IupSetLanguage("SPANISH");
	  IupConfigSetVariableStr(config, "MainWindow", "Language", "SPANISH");
	}
    }

  return r;
}

int preferences_cb(Ihandle *ih)
{
  int width = IupConfigGetVariableIntDef(config, "MainWindow", "widthChalkBoard", 26);
  int height = IupConfigGetVariableIntDef(config, "MainWindow", "heightChalkBoard", 18);
  int lang = 0;

  if ([[NSString stringWithCString: IupConfigGetVariableStrDef(config, "MainWindow", "Language", "ENGLISH")]
	isEqualToString: @"SPANISH"])
    {
      lang = 1;
      IupGetParam("Preferencias", param_action, 0,
		  "Tamaño de pizarra %t\n"
		  "Ancho: %i[26,100]\n"
		  "Alto: %i[18,100]\n"
		  "Lenguaje: %l|Inglés|Español|\n",
		  &width, &height, &lang, NULL);
    }
  else
    {
      IupGetParam("Preferences", param_action, 0,
		  "Chalkboard size %t\n"
		  "Width: %i[26,100]\n"
		  "Height: %i[18,100]\n"
		  "Language: %l|English|Spanish|\n",
		  &width, &height, &lang, NULL);
    }

  return IUP_CONTINUE;
}

int exit_cb (Ihandle *ih)
{
  IupConfigDialogClosed(config, dlg, "MainWindow");
  IupConfigSave(config);
  IupDestroy(config);
  
  return IUP_CLOSE;
}

int togglePanel_cb (Ihandle* ih, int state)
{
  if (state == 1)
    {
      IupConfigSetVariableInt(config, "MainWindow", "HasStartedBefore", state);
    }
  
  return IUP_DEFAULT;
}

@implementation IupInterface

- (void) writeMessage: (NSString *)aMessage;
{
  IupSetAttribute(mline, "APPEND", [aMessage cString]);
}

// Cells info to save the problem
- (NSArray *) cellsInfo
{
  int x;
  Ihandle *a_cell;
  NSMutableArray *an_array = [NSMutableArray array];

  for (x = 0; x < width*height - 1; x++)
    {
      a_cell = IupGetChild(chalkBoard, x);
      
      [an_array addObject: [NSNumber numberWithInteger:
				       IupGetInt(a_cell, "TAG")]];
    }

  return [NSArray arrayWithArray: an_array];
}

// Build a string with the element's info, to display in a tooltip.
- (NSString *) dataOfObject: (NSNumber *)aNumber
{
  int x;
  NSString *field;
  NSString *objectData = @"";
  NSMutableArray *keys, *values;
  
  keys = [[objectsList objectForKey: aNumber] objectForKey: @"Titles"];
  values = [[objectsList objectForKey: aNumber] objectForKey: @"Data"];

  for (x = 0; x < [keys count] - 1; x++)
    {
      field = [NSString stringWithFormat: @"%@  =  %@ \n",
		    [[keys objectAtIndex: x] description],
		  [[values objectAtIndex: x] description]];
      
      objectData = [objectData stringByAppendingString: field];
    }

  field = [NSString stringWithFormat: @"%@  =  %@",
		[[keys objectAtIndex: x] description],
	      [[values objectAtIndex: x] description]];
      
  objectData = [objectData stringByAppendingString: field];

  return objectData;
}

- (void) dealloc
{
  [objectsList release];
  [numberId release];
  [conversionDictionary release];
  [mathProcess release];
  [super dealloc];
}

- (id) initInterface
{
  Ihandle *hbox1, *hbox2, *vbox1, *vbox2;
  Ihandle *list, *btnSolve, *btnClean, *frame, *si, *english, *radio;
  Ihandle *img1, *img2;
  Ihandle *scroll;
  NSBundle *mb = [NSBundle mainBundle];
  mathProcess = [FLProcessMathematics new];

  IupOpen(NULL, NULL);
  IupControlsOpen();

  // Init instance variables.
  unitsSystem = 0;
  objectsList = [NSMutableDictionary dictionary];
  [objectsList retain];
  selectedCell = NULL;
  numberId = nil;
  owner = self;

  // Build the conversion factor dictionary.
  NSString *path = [mb pathForResource: @"conversionFactors"
				ofType: @"plist"];
  conversionDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:
						path];
  [conversionDictionary retain];

  // No image at start.
  image = NULL;
  // No objects at start.
  objects = nil;
  moveObject = NO;

  // Localized strings.
  config = IupConfig();
  IupSetAttribute(config, "APP_NAME", "FisicaLab");
  IupConfigLoad(config);

    if ([[NSString stringWithCString: IupConfigGetVariableStrDef(config, "MainWindow", "Language", "ENGLISH")]
	  isEqualToString: @"SPANISH"])
    {
      IupSetLanguageString("FL_SOLVE", "Resolver");
      IupSetLanguageString("FL_CLEAN", "Limpiar Todo");
      IupSetLanguageString("FL_ENGLISH", "Inglés");
      IupSetLanguageString("FL_DELETE", "Borrar calculos previos.");
      IupSetLanguageString("FL_DATA", "Dato");
      IupSetLanguageString("FL_VALUE", "Valor");
      // Modules
      IupSetLanguageString("FL_MODULE_A", "Cinemática: Puntos");
      IupSetLanguageString("FL_MODULE_B", "Cinemática: Circular");
      IupSetLanguageString("FL_MODULE_C", "Stática: Puntos");
      IupSetLanguageString("FL_MODULE_D", "Stática: Cuerpos rígidos");
      IupSetLanguageString("FL_MODULE_E", "Dinámica: Puntos");
      IupSetLanguageString("FL_MODULE_F", "Dinámica: Circular");
      IupSetLanguageString("FL_MODULE_G", "Calorimetría");
      IupSetLanguageString("FL_MODULE_H", "Termodinámica");
      // Kinematics
      IupSetLanguageString("FL_REF_SYS", "S. Ref.");
      IupSetLanguageString("FL_M_REF_SYS", "S. ref. M.");
      IupSetLanguageString("FL_M_REF_X", "S. ref. x");
      IupSetLanguageString("FL_M_REF_Y", "S. ref. y");
      IupSetLanguageString("FL_MOBILE", "Movil");
      IupSetLanguageString("FL_CANNON", "Cañon");
      IupSetLanguageString("FL_MOBILE_RADIAL", "M. Radial");
      IupSetLanguageString("FL_MOBILE_X", "M. x");
      IupSetLanguageString("FL_MOBILE_Y", "M. y");
      IupSetLanguageString("FL_MOBILE_C_X", "Const. x");
      IupSetLanguageString("FL_MOBILE_C_Y", "Const. y");
      IupSetLanguageString("FL_POINT", "Punto");
      IupSetLanguageString("FL_DISTANCE", "Dist.");
      IupSetLanguageString("FL_DISTANCE_XY", "Dist. XY");
      IupSetLanguageString("FL_REL_VELOCITY", "Vel. Rel.");
      // Circular kinematics
      IupSetLanguageString("FL_MOBILE_CIRCULAR", "M. Circ.");
      IupSetLanguageString("FL_MOBILE_POLAR", "M. Pol.");
      IupSetLanguageString("FL_ANGULAR_VELOCITY", "V. Ang.");
      IupSetLanguageString("FL_ANGULAR_ACCELERATION", "Ac. Ang.");
      IupSetLanguageString("FL_TOTAL_ACCELERATION", "Ac. T.");
      IupSetLanguageString("FL_FREQUENCY", "Frec.");
      IupSetLanguageString("FL_PERIOD", "Periodo");
      IupSetLanguageString("FL_N_LAPS", "N. Vltas.");
      IupSetLanguageString("FL_CENTER", "Centro");
      IupSetLanguageString("FL_ARC_LENGTH", "L. Arco");
      IupSetLanguageString("FL_COORDINATES", "Coord.");
      // Statics
      IupSetLanguageString("FL_BLOCK", "Bloque");
      IupSetLanguageString("FL_BLOCK_LEFT", "B. Iz.");
      IupSetLanguageString("FL_BLOCK_RIGHT", "B. Der.");
      IupSetLanguageString("FL_PULLEY", "Polea");
      IupSetLanguageString("FL_ANGLES", "Ángls.");
      IupSetLanguageString("FL_FORCES", "Fuerzas");
      IupSetLanguageString("FL_RESULTANTS", "Resultantes");
      IupSetLanguageString("FL_SPRINGS", "Resortes");
      IupSetLanguageString("FL_FRICTIONS", "Fric.");
      // Statics of rigid bodies
      IupSetLanguageString("FL_COUPLE", "Torque");
      IupSetLanguageString("FL_TRUSS", "Arm.");
      IupSetLanguageString("FL_JOINT", "Junta");
      IupSetLanguageString("FL_BODIES", "Cuerpos");
      IupSetLanguageString("FL_BEAMS", "Vigas");
      IupSetLanguageString("FL_SOLIDS", "Sólidos");
      IupSetLanguageString("FL_BEAMS_2F", "Vigas 2F");
      IupSetLanguageString("FL_BEAMS_TRUSS", "V. Arm.");
      // Dynamics of points
      IupSetLanguageString("FL_RELATION_ACCELERATIONS", "Rel. a.");
      IupSetLanguageString("FL_RELATIVE_MOTION", "M. Rel.");
      IupSetLanguageString("FL_COLLISION", "Colisión");
      IupSetLanguageString("FL_POWER", "Pot.");
      IupSetLanguageString("FL_MOBILES", "Móviles");
      IupSetLanguageString("FL_BLOCKS", "Bloques");
      IupSetLanguageString("FL_LAW", "Ley");
      IupSetLanguageString("FL_CONTACTS", "Contactos");
      // Circular Dynamics of points
      IupSetLanguageString("FL_MASS_REST", "Rep.");
      IupSetLanguageString("FL_LINEAR", "Lineal");
      IupSetLanguageString("FL_CIRCULAR", "Circ.");
      IupSetLanguageString("FL_POLAR", "Polar");
      IupSetLanguageString("FL_PERPENDICULAR", "Per.");
      IupSetLanguageString("FL_ENERGY", "Energía");
      IupSetLanguageString("FL_ANG_MOMENTUM", "M. Ang.");
      IupSetLanguageString("FL_LIN_MOMENTUM", "M. Lin.");
      IupSetLanguageString("FL_INITIAL_SYS", "Sist. I.");
      IupSetLanguageString("FL_FINAL_SYS", "Sist. F.");
      IupSetLanguageString("FL_TRIANGLE_FORCES", "Triáng.");
      IupSetLanguageString("FL_MAX_ACCELERATION", "A. Máx.");
      IupSetLanguageString("FL_CENTRIPETAL_ACCELERATION", "Ac. C.");
      IupSetLanguageString("FL_INERTIA", "Inercia");
      IupSetLanguageString("FL_ABSOLUTE_VELOCITY", "V. Abs.");
      IupSetLanguageString("FL_SINE", "Seno");
      // Calorimetry
      IupSetLanguageString("FL_TIME_LAB", "T. Lab.");
      IupSetLanguageString("FL_HEAT_IN", "Calor");
      IupSetLanguageString("FL_HEAT_FLOW_IN", "Flujo C.");
      IupSetLanguageString("FL_HEAT_OUT", "Ex. C.");
      IupSetLanguageString("FL_HEAT_FLOW_OUT", "Ref.");
      IupSetLanguageString("FL_LIQUID", "Liquido");
      IupSetLanguageString("FL_GAS", "Gas");
      IupSetLanguageString("FL_EXCHANGER", "Int.");
      IupSetLanguageString("FL_EXPANSION", "Dilt.");
      IupSetLanguageString("FL_CHANGE", "Cambio");
      IupSetLanguageString("FL_CALORIMETER", "Calorím.");
      // Thermodynamics
      IupSetLanguageString("FL_WORK", "Trab.");
      IupSetLanguageString("FL_ADIABATIC_PROC", "P. Ad.");
      IupSetLanguageString("FL_ISOCHORIC_PROC", "P. Isc.");
      IupSetLanguageString("FL_ISOTHERMIC_PROC", "P. Ist.");
      IupSetLanguageString("FL_ISOBARIC_PROC", "P. Isb.");
      IupSetLanguageString("FL_SENSIBLE_HEAT", "C. Sen.");
      IupSetLanguageString("FL_VAPORIZATION_HEAT", "C. Vap.");
      IupSetLanguageString("FL_HEAT_ENGINE", "M. Tér.");
      IupSetLanguageString("FL_REFRIGERATOR", "Ref.");
      IupSetLanguageString("FL_HEAT_PUMP", "Bomba");
      // Menu and window
      IupSetLanguageString("FL_MENU_ABOUT", "Acerca...");
      IupSetLanguageString("FL_MENU_PREFERENCES", "Preferencias...");
      IupSetLanguageString("FL_MENU_QUIT", "Salir");
      IupSetLanguageString("FL_MENU_TITLE", "FísicaLab");
      IupSetLanguageString("FL_WINDOW_TITLE", "FísicaLab");
      // First launch panel
      IupSetLanguageString("FL_LOGO_PANEL", "No mostrar de nuevo.");
    }
  else
    {
      IupSetLanguageString("FL_SOLVE", "Solve");
      IupSetLanguageString("FL_CLEAN", "Clean All");
      IupSetLanguageString("FL_ENGLISH", "English");
      IupSetLanguageString("FL_DELETE", "Delete previous calculations.");
      IupSetLanguageString("FL_DATA", "Data");
      IupSetLanguageString("FL_VALUE", "Value");
      // Modules
      IupSetLanguageString("FL_MODULE_A", "Kinematics: Points");
      IupSetLanguageString("FL_MODULE_B", "Kinematics: Circular");
      IupSetLanguageString("FL_MODULE_C", "Statics: Points");
      IupSetLanguageString("FL_MODULE_D", "Statics: Rigid bodies");
      IupSetLanguageString("FL_MODULE_E", "Dynamics: Points");
      IupSetLanguageString("FL_MODULE_F", "Dynamics: Circular");
      IupSetLanguageString("FL_MODULE_G", "Calorimetry");
      IupSetLanguageString("FL_MODULE_H", "Thermodynamics");
      // Kinematics
      IupSetLanguageString("FL_REF_SYS", "R. Sys.");
      IupSetLanguageString("FL_M_REF_SYS", "M. ref. S.");
      IupSetLanguageString("FL_M_REF_X", "M. ref. x");
      IupSetLanguageString("FL_M_REF_Y", "M. ref. y");
      IupSetLanguageString("FL_MOBILE", "Mobile");
      IupSetLanguageString("FL_CANNON", "Cannon");
      IupSetLanguageString("FL_MOBILE_RADIAL", "M. Radial");
      IupSetLanguageString("FL_MOBILE_X", "M. x");
      IupSetLanguageString("FL_MOBILE_Y", "M. y");
      IupSetLanguageString("FL_MOBILE_C_X", "Const. x");
      IupSetLanguageString("FL_MOBILE_C_Y", "Const. y");
      IupSetLanguageString("FL_POINT", "Point");
      IupSetLanguageString("FL_DISTANCE", "Dist.");
      IupSetLanguageString("FL_DISTANCE_XY", "Dist. XY");
      IupSetLanguageString("FL_REL_VELOCITY", "Rel. Vel.");
      // Circular kinematics
      IupSetLanguageString("FL_MOBILE_CIRCULAR", "Circ. M.");
      IupSetLanguageString("FL_MOBILE_POLAR", "Pol. M.");
      IupSetLanguageString("FL_ANGULAR_VELOCITY", "Ang. V.");
      IupSetLanguageString("FL_ANGULAR_ACCELERATION", "Ang. A.");
      IupSetLanguageString("FL_TOTAL_ACCELERATION", "T. Acc.");
      IupSetLanguageString("FL_FREQUENCY", "Freq.");
      IupSetLanguageString("FL_PERIOD", "Period");
      IupSetLanguageString("FL_N_LAPS", "N. Laps");
      IupSetLanguageString("FL_CENTER", "Cent.");
      IupSetLanguageString("FL_ARC_LENGTH", "Arc. L.");
      IupSetLanguageString("FL_COORDINATES", "Coord.");
      // Statics
      IupSetLanguageString("FL_BLOCK", "Block");
      IupSetLanguageString("FL_BLOCK_LEFT", "B. Left");
      IupSetLanguageString("FL_BLOCK_RIGHT", "B. Right");
      IupSetLanguageString("FL_PULLEY", "Pulley");
      IupSetLanguageString("FL_ANGLES", "Angles");
      IupSetLanguageString("FL_FORCES", "Forces");
      IupSetLanguageString("FL_RESULTANTS", "Resultants");
      IupSetLanguageString("FL_SPRINGS", "Springs");
      IupSetLanguageString("FL_FRICTIONS", "Frict.");
      // Statics of rigid bodies
      IupSetLanguageString("FL_COUPLE", "Couple");
      IupSetLanguageString("FL_TRUSS", "Truss");
      IupSetLanguageString("FL_JOINT", "Joint");
      IupSetLanguageString("FL_BODIES", "Bodies");
      IupSetLanguageString("FL_BEAMS", "Beams");
      IupSetLanguageString("FL_SOLIDS", "Solids");
      IupSetLanguageString("FL_BEAMS_2F", "Beams 2F");
      IupSetLanguageString("FL_BEAMS_TRUSS", "B. Trs.");
      // Dynamics of points
      IupSetLanguageString("FL_RELATION_ACCELERATIONS", "Rel. a.");
      IupSetLanguageString("FL_RELATIVE_MOTION", "Rel. m.");
      IupSetLanguageString("FL_COLLISION", "Coll.");
      IupSetLanguageString("FL_POWER", "Power");
      IupSetLanguageString("FL_MOBILES", "Mobiles");
      IupSetLanguageString("FL_BLOCKS", "Blocks");
      IupSetLanguageString("FL_LAW", "Law");
      IupSetLanguageString("FL_CONTACTS", "Contacts");
      // Circular Dynamics of points
      IupSetLanguageString("FL_MASS_REST", "Rest");
      IupSetLanguageString("FL_LINEAR", "Linear");
      IupSetLanguageString("FL_CIRCULAR", "Circ.");
      IupSetLanguageString("FL_POLAR", "Polar");
      IupSetLanguageString("FL_PERPENDICULAR", "Per.");
      IupSetLanguageString("FL_ENERGY", "Energy");
      IupSetLanguageString("FL_ANG_MOMENTUM", "Ang. M.");
      IupSetLanguageString("FL_LIN_MOMENTUM", "Lin. M.");
      IupSetLanguageString("FL_INITIAL_SYS", "I. Sys.");
      IupSetLanguageString("FL_FINAL_SYS", "F. Sys.");
      IupSetLanguageString("FL_TRIANGLE_FORCES", "Triang.");
      IupSetLanguageString("FL_MAX_ACCELERATION", "M. Ac.");
      IupSetLanguageString("FL_CENTRIPETAL_ACCELERATION", "C. Ac.");
      IupSetLanguageString("FL_INERTIA", "Inertia");
      IupSetLanguageString("FL_ABSOLUTE_VELOCITY", "Abs. V.");
      IupSetLanguageString("FL_SINE", "Sine");
      // Calorimetry
      IupSetLanguageString("FL_TIME_LAB", "T. Lab.");
      IupSetLanguageString("FL_HEAT_IN", "Heat");
      IupSetLanguageString("FL_HEAT_FLOW_IN", "Flow H.");
      IupSetLanguageString("FL_HEAT_OUT", "Ex. H.");
      IupSetLanguageString("FL_HEAT_FLOW_OUT", "Ref.");
      IupSetLanguageString("FL_LIQUID", "Liquid");
      IupSetLanguageString("FL_GAS", "Gas");
      IupSetLanguageString("FL_EXCHANGER", "Exch.");
      IupSetLanguageString("FL_EXPANSION", "Exp.");
      IupSetLanguageString("FL_CHANGE", "Change");
      IupSetLanguageString("FL_CALORIMETER", "Calorim.");
      // Thermodynamics
      IupSetLanguageString("FL_WORK", "Work");
      IupSetLanguageString("FL_ADIABATIC_PROC", "Ad. P.");
      IupSetLanguageString("FL_ISOCHORIC_PROC", "Is. P.");
      IupSetLanguageString("FL_ISOTHERMIC_PROC", "Ist. P.");
      IupSetLanguageString("FL_ISOBARIC_PROC", "Isb. P.");
      IupSetLanguageString("FL_SENSIBLE_HEAT", "S. Heat");
      IupSetLanguageString("FL_VAPORIZATION_HEAT", "V. Heat");
      IupSetLanguageString("FL_HEAT_ENGINE", "H. Eng.");
      IupSetLanguageString("FL_REFRIGERATOR", "Ref.");
      IupSetLanguageString("FL_HEAT_PUMP", "H. Pump");
      // Menu and window
      IupSetLanguageString("FL_MENU_ABOUT", "About...");
      IupSetLanguageString("FL_MENU_PREFERENCES", "Preferences...");
      IupSetLanguageString("FL_MENU_QUIT", "Quit");
      IupSetLanguageString("FL_MENU_TITLE", "FisicaLab");
      IupSetLanguageString("FL_WINDOW_TITLE", "FisicaLab");
      // First launch panel
      IupSetLanguageString("FL_LOGO_PANEL", "Don't show again.");
    }

  // Load all the neccesary images.
  img1 = IupLoadImage([[mb pathForResource: @"solve" ofType: @"tif"] cString]);
  img2 = IupLoadImage([[mb pathForResource: @"clean" ofType: @"tif"] cString]);

  btnSolve = IupButton("",NULL);
  IupSetStrf(btnSolve, "TIP", "_@FL_SOLVE");
  IupSetAttributeHandle(btnSolve, "IMAGE", img1);
  IupSetCallback(btnSolve, "ACTION", (Icallback)solve_cb);
  btnClean = IupButton("", NULL);
  IupSetStrf(btnClean, "TIP", "_@FL_CLEAN");
  IupSetAttributeHandle(btnClean, "IMAGE", img2);
  IupSetCallback(btnClean, "ACTION", (Icallback)clean_cb);
  
  toggle = IupToggle("_@FL_DELETE", NULL);
  IupSetAttribute(toggle, "VALUE", "ON");
  mline = IupMultiLine(NULL);
  IupSetAttribute(mline, "APPENDNEWLINE", "NO");
  IupSetAttribute(mline, "VISIBLELINES", "4");
  IupSetAttribute(mline, "EXPAND", "HORIZONTAL");

  // Module kinematics of points
  Ihandle *ik1, *ik2, *ik3, *ik4, *ik5, *ik6, *ik7, *ik8, *ik9, *ik10, *ik11, *ik12, *ik13, *ik14, *ik15;
  Ihandle *bk1, *bk2, *bk3, *bk4, *bk5, *bk6, *bk7, *bk8, *bk9, *bk10, *bk11, *bk12, *bk13, *bk14, *bk15, *kgridbox1;
  
  ik1 = IupLoadImage([[mb pathForResource: @"reference_system" ofType: @"tif"] cString]);
  ik2 = IupLoadImage([[mb pathForResource: @"mobile_reference_system" ofType: @"tif"] cString]);
  ik3 = IupLoadImage([[mb pathForResource: @"mobile_reference_system_x" ofType: @"tif"] cString]);
  ik4 = IupLoadImage([[mb pathForResource: @"mobile_reference_system_y" ofType: @"tif"] cString]);
  ik5 = IupLoadImage([[mb pathForResource: @"mobile" ofType: @"tif"] cString]);
  ik6 = IupLoadImage([[mb pathForResource: @"cannon" ofType: @"tif"] cString]);
  ik7 = IupLoadImage([[mb pathForResource: @"mobile_radial" ofType: @"tif"] cString]);
  ik8 = IupLoadImage([[mb pathForResource: @"mobile_x" ofType: @"tif"] cString]);
  ik9 = IupLoadImage([[mb pathForResource: @"mobile_y" ofType: @"tif"] cString]);
  ik10 = IupLoadImage([[mb pathForResource: @"mobile_const_x" ofType: @"tif"] cString]);
  ik11 = IupLoadImage([[mb pathForResource: @"mobile_const_y" ofType: @"tif"] cString]);
  ik12 = IupLoadImage([[mb pathForResource: @"point" ofType: @"tif"] cString]);
  ik13 = IupLoadImage([[mb pathForResource: @"distance" ofType: @"tif"] cString]);
  ik14 = IupLoadImage([[mb pathForResource: @"distance_xy" ofType: @"tif"] cString]);
  ik15 = IupLoadImage([[mb pathForResource: @"relative_velocity" ofType: @"tif"] cString]);

  bk1 = IupFlatButton("_@FL_REF_SYS");
  IupSetAttributeHandle(bk1, "IMAGE", ik1);
  IupSetAttribute(bk1, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk1, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk1, "TAG", 1);
  bk2 = IupFlatButton("_@FL_M_REF_SYS");
  IupSetAttributeHandle(bk2, "IMAGE", ik2);
  IupSetAttribute(bk2, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk2, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk2, "TAG", 2);
  bk3 = IupFlatButton("_@FL_M_REF_X");
  IupSetAttributeHandle(bk3, "IMAGE", ik3);
  IupSetAttribute(bk3, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk3, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk3, "TAG", 7);
  bk4 = IupFlatButton("_@FL_M_REF_Y");
  IupSetAttributeHandle(bk4, "IMAGE", ik4);
  IupSetAttribute(bk4, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk4, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk4, "TAG", 8);
  bk5 = IupFlatButton("_@FL_MOBILE");
  IupSetAttributeHandle(bk5, "IMAGE", ik5);
  IupSetAttribute(bk5, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk5, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk5, "TAG", 3);
  bk6 = IupFlatButton("_@FL_CANNON");
  IupSetAttributeHandle(bk6, "IMAGE", ik6);
  IupSetAttribute(bk6, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk6, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk6, "TAG", 4);
  bk7 = IupFlatButton("_@FL_MOBILE_RADIAL");
  IupSetAttributeHandle(bk7, "IMAGE", ik7);
  IupSetAttribute(bk7, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk7, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk7, "TAG", 13);
  bk8 = IupFlatButton("_@FL_MOBILE_X");
  IupSetAttributeHandle(bk8, "IMAGE", ik8);
  IupSetAttribute(bk8, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk8, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk8, "TAG", 5);
  bk9 = IupFlatButton("_@FL_MOBILE_Y");
  IupSetAttributeHandle(bk9, "IMAGE", ik9);
  IupSetAttribute(bk9, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk9, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk9, "TAG", 6);
  bk10 = IupFlatButton("_@FL_MOBILE_C_X");
  IupSetAttributeHandle(bk10, "IMAGE", ik10);
  IupSetAttribute(bk10, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk10, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk10, "TAG", 9);
  bk11 = IupFlatButton("_@FL_MOBILE_C_Y");
  IupSetAttributeHandle(bk11, "IMAGE", ik11);
  IupSetAttribute(bk11, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk11, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk11, "TAG", 10);
  bk12 = IupFlatButton("_@FL_POINT");
  IupSetAttributeHandle(bk12, "IMAGE", ik12);
  IupSetAttribute(bk12, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk12, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk12, "TAG", 15);
  bk13 = IupFlatButton("_@FL_DISTANCE");
  IupSetAttributeHandle(bk13, "IMAGE", ik13);
  IupSetAttribute(bk13, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk13, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk13, "TAG", 11);
  bk14 = IupFlatButton("_@FL_DISTANCE_XY");
  IupSetAttributeHandle(bk14, "IMAGE", ik14);
  IupSetAttribute(bk14, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk14, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk14, "TAG", 14);
  bk15 = IupFlatButton("_@FL_REL_VELOCITY");
  IupSetAttributeHandle(bk15, "IMAGE", ik15);
  IupSetAttribute(bk15, "IMAGEPOSITION", "TOP");
  IupSetCallback(bk15, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bk15, "TAG", 12);

  kgridbox1 = IupGridBox(bk1, bk2, bk3, bk4, bk5, bk6, bk7, bk8, bk9, bk10, bk11, bk12, bk13, bk14, bk15, NULL);
  IupSetAttribute(kgridbox1, "NUMDIV", "4");
  IupSetAttribute(kgridbox1, "GAPCOL", "5");
  IupSetAttribute(kgridbox1, "ALIGNMENTCOL", "ACENTER");
  IupSetAttribute(kgridbox1, "SIZELIN", "0");
  IupSetAttribute(kgridbox1, "NORMALIZESIZE", "YES");
  //IupSetAttribute(kgridbox1, "EXPANDCHILDREN", "YES");

  // Module circular kinematics of points
  Ihandle *ikc1, *ikc2, *ikc3, *ikc4, *ikc5, *ikc6, *ikc7, *ikc8, *ikc9, *ikc10, *ikc11, *ikc12, *ikc13, *ikc14;
  Ihandle *bkc1, *bkc2, *bkc3, *bkc4, *bkc5, *bkc6, *bkc7, *bkc8, *bkc9, *bkc10, *bkc11, *bkc12, *bkc13, *bkc14, *kgridbox2;
  
  ikc1 = IupLoadImage([[mb pathForResource: @"reference_system" ofType: @"tif" ] cString]);
  ikc2 = IupLoadImage([[mb pathForResource: @"mobile_circular" ofType: @"tif" ] cString]);
  ikc3 = IupLoadImage([[mb pathForResource: @"mobile_polar" ofType: @"tif" ] cString]);
  ikc4 = IupLoadImage([[mb pathForResource: @"angular_velocity" ofType: @"tif" ] cString]);
  ikc5 = IupLoadImage([[mb pathForResource: @"angular_acceleration" ofType: @"tif" ] cString]);
  ikc6 = IupLoadImage([[mb pathForResource: @"total_acceleration" ofType: @"tif" ] cString]);
  ikc7 = IupLoadImage([[mb pathForResource: @"frequency" ofType: @"tif" ] cString]);
  ikc8 = IupLoadImage([[mb pathForResource: @"period" ofType: @"tif" ] cString]);
  ikc9 = IupLoadImage([[mb pathForResource: @"number_laps" ofType: @"tif" ] cString]);
  ikc10 = IupLoadImage([[mb pathForResource: @"center_rotation" ofType: @"tif" ] cString]);
  ikc11 = IupLoadImage([[mb pathForResource: @"distance" ofType: @"tif" ] cString]);
  ikc12 = IupLoadImage([[mb pathForResource: @"arc_length" ofType: @"tif" ] cString]);
  ikc13 = IupLoadImage([[mb pathForResource: @"coordinate" ofType: @"tif" ] cString]);
  ikc14 = IupLoadImage([[mb pathForResource: @"relative_velocity" ofType: @"tif" ] cString]);

  bkc1 = IupFlatButton("_@FL_REF_SYS");
  IupSetAttributeHandle(bkc1, "IMAGE", ikc1);
  IupSetAttribute(bkc1, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc1, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc1, "TAG", 200);
  bkc2 = IupFlatButton("_@FL_MOBILE_CIRCULAR");
  IupSetAttributeHandle(bkc2, "IMAGE", ikc2);
  IupSetAttribute(bkc2, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc2, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc2, "TAG", 201);
  bkc3 = IupFlatButton("_@FL_MOBILE_POLAR");
  IupSetAttributeHandle(bkc3, "IMAGE", ikc3);
  IupSetAttribute(bkc3, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc3, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc3, "TAG", 202);
  bkc4 = IupFlatButton("_@FL_ANGULAR_VELOCITY");
  IupSetAttributeHandle(bkc4, "IMAGE", ikc4);
  IupSetAttribute(bkc4, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc4, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc4, "TAG", 203);
  bkc5 = IupFlatButton("_@FL_ANGULAR_ACCELERATION");
  IupSetAttributeHandle(bkc5, "IMAGE", ikc5);
  IupSetAttribute(bkc5, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc5, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc5, "TAG", 204);
  bkc6 = IupFlatButton("_@FL_TOTAL_ACCELERATION");
  IupSetAttributeHandle(bkc6, "IMAGE", ikc6);
  IupSetAttribute(bkc6, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc6, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc6, "TAG", 205);
  bkc7 = IupFlatButton("_@FL_FREQUENCY");
  IupSetAttributeHandle(bkc7, "IMAGE", ikc7);
  IupSetAttribute(bkc7, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc7, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc7, "TAG", 206);
  bkc8 = IupFlatButton("_@FL_PERIOD");
  IupSetAttributeHandle(bkc8, "IMAGE", ikc8);
  IupSetAttribute(bkc8, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc8, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc8, "TAG", 207);
  bkc9 = IupFlatButton("_@FL_N_LAPS");
  IupSetAttributeHandle(bkc9, "IMAGE", ikc9);
  IupSetAttribute(bkc9, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc9, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc9, "TAG", 208);
  bkc10 = IupFlatButton("_@FL_CENTER");
  IupSetAttributeHandle(bkc10, "IMAGE", ikc10);
  IupSetAttribute(bkc10, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc10, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc10, "TAG", 209);
  bkc11 = IupFlatButton("_@FL_DISTANCE");
  IupSetAttributeHandle(bkc11, "IMAGE", ikc11);
  IupSetAttribute(bkc11, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc11, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc11, "TAG", 210);
  bkc12 = IupFlatButton("_@FL_ARC_LENGTH");
  IupSetAttributeHandle(bkc12, "IMAGE", ikc12);
  IupSetAttribute(bkc12, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc12, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc12, "TAG", 211);
  bkc13 = IupFlatButton("_@FL_COORDINATES");
  IupSetAttributeHandle(bkc13, "IMAGE", ikc13);
  IupSetAttribute(bkc13, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc13, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc13, "TAG", 212);
  bkc14 = IupFlatButton("_@FL_REL_VELOCITY");
  IupSetAttributeHandle(bkc14, "IMAGE", ikc14);
  IupSetAttribute(bkc14, "IMAGEPOSITION", "TOP");
  IupSetCallback(bkc14, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bkc14, "TAG", 213);

  kgridbox2 = IupGridBox(bkc1, bkc2, bkc3, bkc4, bkc5, bkc6, bkc7, bkc8, bkc9, bkc10, bkc11, bkc12, bkc13, bkc14, NULL);
  IupSetAttribute(kgridbox2, "NUMDIV", "4");
  IupSetAttribute(kgridbox2, "GAPCOL", "5");
  IupSetAttribute(kgridbox2, "ALIGNMENTCOL", "ACENTER");
  IupSetAttribute(kgridbox2, "SIZELIN", "1");
  IupSetAttribute(kgridbox2, "NORMALIZESIZE", "YES");
  //IupSetAttribute(kgridbox2, "EXPANDCHILDREN", "YES");

  // Statics of points
  Ihandle *is1, *is2, *is3, *is4, *is5, *is6, *is7, *is8, *is9, *is10, *is11;
  Ihandle *bs1, *bs2, *bs3, *bs4, *bs5, *bs6, *bs7, *bs8, *bs9, *bs10, *bs11, *sgridbox1, *svbox;
  
  is1 = IupLoadImage([[mb pathForResource: @"reference_system" ofType: @"tif" ] cString]);
  is2 = IupLoadImage([[mb pathForResource: @"block" ofType: @"tif" ] cString]);
  is3 = IupLoadImage([[mb pathForResource: @"block_left" ofType: @"tif" ] cString]);
  is4 = IupLoadImage([[mb pathForResource: @"block_right" ofType: @"tif" ] cString]);
  is5 = IupLoadImage([[mb pathForResource: @"pulley" ofType: @"tif" ] cString]);
  is6 = IupLoadImage([[mb pathForResource: @"point_static" ofType: @"tif" ] cString]);
  is7 = IupLoadImage([[mb pathForResource: @"relation_angles" ofType: @"tif" ] cString]);
  is8 = IupLoadImage([[mb pathForResource: @"springs" ofType: @"tif" ] cString]);
  is9 = IupLoadImage([[mb pathForResource: @"resultants" ofType: @"tif" ] cString]);
  is10 = IupLoadImage([[mb pathForResource: @"forces" ofType: @"tif" ] cString]);
  is11 = IupLoadImage([[mb pathForResource: @"frictions" ofType: @"tif" ] cString]);

  bs1 = IupFlatButton("_@FL_REF_SYS");
  IupSetAttributeHandle(bs1, "IMAGE", is1);
  IupSetAttribute(bs1, "IMAGEPOSITION", "TOP");
  IupSetCallback(bs1, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bs1, "TAG", 50);
  bs2 = IupFlatButton("_@FL_BLOCK");
  IupSetAttributeHandle(bs2, "IMAGE", is2);
  IupSetAttribute(bs2, "IMAGEPOSITION", "TOP");
  IupSetCallback(bs2, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bs2, "TAG", 51);
  bs3 = IupFlatButton("_@FL_BLOCK_LEFT");
  IupSetAttributeHandle(bs3, "IMAGE", is3);
  IupSetAttribute(bs3, "IMAGEPOSITION", "TOP");
  IupSetCallback(bs3, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bs3, "TAG", 52);
  bs4 = IupFlatButton("_@FL_BLOCK_RIGHT");
  IupSetAttributeHandle(bs4, "IMAGE", is4);
  IupSetAttribute(bs4, "IMAGEPOSITION", "TOP");
  IupSetCallback(bs4, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bs4, "TAG", 53);
  bs5 = IupFlatButton("_@FL_PULLEY");
  IupSetAttributeHandle(bs5, "IMAGE", is5);
  IupSetAttribute(bs5, "IMAGEPOSITION", "TOP");
  IupSetCallback(bs5, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bs5, "TAG", 54);
  bs6 = IupFlatButton("_@FL_POINT");
  IupSetAttributeHandle(bs6, "IMAGE", is6);
  IupSetAttribute(bs6, "IMAGEPOSITION", "TOP");
  IupSetCallback(bs6, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bs6, "TAG", 55);
  bs7 = IupFlatButton("_@FL_ANGLES");
  IupSetAttributeHandle(bs7, "IMAGE", is7);
  IupSetAttribute(bs7, "IMAGEPOSITION", "TOP");
  IupSetCallback(bs7, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bs7, "TAG", 79);
  bs8 = IupFlatButton(NULL);
  IupSetAttributeHandle(bs8, "IMAGE", is8);
  IupSetAttribute(bs8, "IMAGEPOSITION", "TOP");
  IupSetCallback(bs8, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bs8, "TAG", 75);
  bs9 = IupFlatButton(NULL);
  IupSetAttributeHandle(bs9, "IMAGE", is9);
  IupSetAttribute(bs9, "IMAGEPOSITION", "TOP");
  IupSetCallback(bs9, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bs9, "TAG", 72);
  bs10 = IupFlatButton(NULL);
  IupSetAttributeHandle(bs10, "IMAGE", is10);
  //IupSetAttribute(bs10, "IMAGEPOSITION", "TOP");
  IupSetCallback(bs10, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bs10, "TAG", 56);
  bs11 = IupFlatButton(NULL);
  IupSetAttributeHandle(bs11, "IMAGE", is11);
  IupSetAttribute(bs11, "IMAGEPOSITION", "TOP");
  IupSetCallback(bs11, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bs11, "TAG", 64);

  sgridbox1 = IupGridBox(bs1, bs2, bs3, bs4, bs5, bs6, bs7, NULL);
  IupSetAttribute(sgridbox1, "NUMDIV", "4");
  IupSetAttribute(sgridbox1, "GAPCOL", "5");
  IupSetAttribute(sgridbox1, "ALIGNMENTCOL", "ACENTER");
  IupSetAttribute(sgridbox1, "SIZELIN", "1");
  //IupSetAttribute(sgridbox1, "NORMALIZESIZE", "YES");

  Ihandle *sframe1, *sframe2, *sframe3, *sframe4, *shbox1, *shbox2;

  sframe1 = IupFrame(bs8);
  IupSetStrf(sframe1, "TITLE", "_@FL_SPRINGS");
  sframe2 = IupFrame(bs9);
  IupSetStrf(sframe2, "TITLE", "_@FL_RESULTANTS");
  sframe3 = IupFrame(bs10);
  IupSetStrf(sframe3, "TITLE", "_@FL_FORCES");
  sframe4 = IupFrame(bs11);
  IupSetStrf(sframe4, "TITLE", "_@FL_FRICTIONS");

  shbox1 = IupHbox(sframe1, sframe2, NULL);
  IupSetAttribute(shbox1, "GAP", "3");
  //shbox2 = IupHbox(IupFill(), sframe3, sframe4, NULL);
  shbox2 = IupHbox(sframe3, sframe4, NULL);
  IupSetAttribute(shbox2, "GAP", "5");
  
  svbox = IupVbox(sgridbox1, shbox1, shbox2, NULL);
  IupSetAttribute(svbox, "GAP", "3");

  // Statics of rigid bodies
  Ihandle *isr1, *isr2, *isr3, *isr4, *isr5, *isr6, *isr7, *isr8, *isr9, *isr10,
    *isr11, *isr12, *isr13, *isr14, *isr15, *isr16;
  Ihandle *bsr1, *bsr2, *bsr3, *bsr4, *bsr5, *bsr6, *bsr7, *bsr8, *bsr9, *bsr10,
    *bsr11, *bsr12, *bsr13, *bsr14, *bsr15, *bsr16,
    *bodiesBox, *srgridbox1, *srvbox;

  isr1 = IupLoadImage([[mb pathForResource: @"reference_system" ofType: @"tif" ] cString]);
  isr2 = IupLoadImage([[mb pathForResource: @"point" ofType: @"tif" ] cString]);
  isr3 = IupLoadImage([[mb pathForResource: @"bodies" ofType: @"tif" ] cString]);
  isr4 = IupLoadImage([[mb pathForResource: @"couple" ofType: @"tif" ] cString]);
  isr5 = IupLoadImage([[mb pathForResource: @"truss" ofType: @"tif" ] cString]);
  isr6 = IupLoadImage([[mb pathForResource: @"joint" ofType: @"tif" ] cString]);
  isr7 = IupLoadImage([[mb pathForResource: @"relation_angles" ofType: @"tif" ] cString]);
  isr8 = IupLoadImage([[mb pathForResource: @"beams" ofType: @"tif" ] cString]);
  isr9 = IupLoadImage([[mb pathForResource: @"solids_1" ofType: @"tif" ] cString]);
  isr10 = IupLoadImage([[mb pathForResource: @"solids_2" ofType: @"tif" ] cString]);
  isr11 = IupLoadImage([[mb pathForResource: @"solids_3" ofType: @"tif" ] cString]);
  isr12 = IupLoadImage([[mb pathForResource: @"forces" ofType: @"tif" ] cString]);
  isr13 = IupLoadImage([[mb pathForResource: @"frictions" ofType: @"tif" ] cString]);
  isr14 = IupLoadImage([[mb pathForResource: @"beams_2F" ofType: @"tif" ] cString]);
  isr15 = IupLoadImage([[mb pathForResource: @"beams_truss" ofType: @"tif" ] cString]);
  isr16 = IupLoadImage([[mb pathForResource: @"resultants_rigid" ofType: @"tif" ] cString]);

  bsr1 = IupFlatButton("_@FL_REF_SYS");
  IupSetAttributeHandle(bsr1, "IMAGE", isr1);
  IupSetAttribute(bsr1, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr1, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bsr1, "TAG", 250);
  bsr2 = IupFlatButton("_@FL_POINT");
  IupSetAttributeHandle(bsr2, "IMAGE", isr2);
  IupSetAttribute(bsr2, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr2, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bsr2, "TAG", 251);
  bsr3 = IupFlatButton(NULL);
  IupSetAttributeHandle(bsr3, "IMAGE", isr3);
  IupSetAttribute(bsr3, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr3, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bsr3, "TAG", 252);
  bsr4 = IupFlatButton("_@FL_COUPLE");
  IupSetAttributeHandle(bsr4, "IMAGE", isr4);
  IupSetAttribute(bsr4, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr4, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bsr4, "TAG", 254);
  bsr5 = IupFlatButton("_@FL_TRUSS");
  IupSetAttributeHandle(bsr5, "IMAGE", isr5);
  IupSetAttribute(bsr5, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr5, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bsr5, "TAG", 293);
  bsr6 = IupFlatButton("_@FL_JOINT");
  IupSetAttributeHandle(bsr6, "IMAGE", isr6);
  IupSetAttribute(bsr6, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr6, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bsr6, "TAG", 294);
  bsr7 = IupFlatButton("_@FL_ANGLES");
  IupSetAttributeHandle(bsr7, "IMAGE", isr7);
  IupSetAttribute(bsr7, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr7, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bsr7, "TAG", 295);
  bsr8 = IupFlatButton(NULL);
  IupSetAttributeHandle(bsr8, "IMAGE", isr8);
  IupSetAttribute(bsr8, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr8, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bsr8, "TAG", 255);
  bsr9 = IupFlatButton(NULL);
  IupSetAttributeHandle(bsr9, "IMAGE", isr9);
  IupSetAttribute(bsr9, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr9, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bsr9, "TAG", 500);
  bsr10 = IupFlatButton(NULL);
  IupSetAttributeHandle(bsr10, "IMAGE", isr10);
  //IupSetAttribute(bsr10, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr10, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bsr10, "TAG", 501);
  bsr11 = IupFlatButton(NULL);
  IupSetAttributeHandle(bsr11, "IMAGE", isr11);
  IupSetAttribute(bsr11, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr11, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bsr11, "TAG", 502);
  bsr12 = IupFlatButton(NULL);
  IupSetAttributeHandle(bsr12, "IMAGE", isr12);
  IupSetAttribute(bsr12, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr12, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bsr12, "TAG", 257);
  bsr13 = IupFlatButton(NULL);
  IupSetAttributeHandle(bsr13, "IMAGE", isr13);
  IupSetAttribute(bsr13, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr13, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bsr13, "TAG", 265);
  bsr14 = IupFlatButton(NULL);
  IupSetAttributeHandle(bsr14, "IMAGE", isr14);
  IupSetAttribute(bsr14, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr14, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bsr14, "TAG", 277);
  bsr15 = IupFlatButton(NULL);
  IupSetAttributeHandle(bsr15, "IMAGE", isr15);
  IupSetAttribute(bsr15, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr15, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bsr15, "TAG", 285);
  bsr16 = IupFlatButton(NULL);
  IupSetAttributeHandle(bsr16, "IMAGE", isr16);
  IupSetAttribute(bsr16, "IMAGEPOSITION", "TOP");
  IupSetCallback(bsr16, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bsr16, "TAG", 273);

  bodiesBox = IupVbox(bsr3, IupLabel("_@FL_BODIES"), NULL);
  IupSetAttribute(bodiesBox, "ALIGNMENT", "ACENTER");

  srgridbox1 = IupGridBox(bsr1, bsr2, bodiesBox, bsr4,
			  bsr5, bsr6, bsr7, NULL);
  IupSetAttribute(srgridbox1, "NUMDIV", "4");
  IupSetAttribute(srgridbox1, "GAPCOL", "5");
  IupSetAttribute(srgridbox1, "ALIGNMENTCOL", "ACENTER");
  IupSetAttribute(srgridbox1, "SIZELIN", "0");
  IupSetAttribute(srgridbox1, "NORMALIZESIZE", "YES");

  Ihandle *srframe1, *srframe2, *srframe3, *srframe4, *srframe5, *srframe6, *srframe7, *srhbox1, *srhbox2, *srhbox3;

  srframe1 = IupFrame(bsr8);
  IupSetStrf(srframe1, "TITLE", "_@FL_BEAMS");
  srframe2 = IupFrame(IupVbox(bsr9, bsr10, bsr11, NULL));
  IupSetStrf(srframe2, "TITLE", "_@FL_SOLIDS");
  srframe3 = IupFrame(bsr12);
  IupSetStrf(srframe3, "TITLE", "_@FL_FORCES");
  srframe4 = IupFrame(bsr13);
  IupSetStrf(srframe4, "TITLE", "_@FL_FRICTIONS");
  srframe5 = IupFrame(bsr14);
  IupSetStrf(srframe5, "TITLE", "_@FL_BEAMS_2F");
  srframe6 = IupFrame(bsr15);
  IupSetStrf(srframe6, "TITLE", "_@FL_BEAMS_TRUSS");
  srframe7 = IupFrame(bsr16);
  IupSetStrf(srframe7, "TITLE", "_@FL_RESULTANTS");

  srhbox1 = IupHbox(srframe1, srframe2, NULL);
  IupSetAttribute(srhbox1, "GAP", "5");
  IupSetAttribute(srhbox1, "MARGIN", "3x0");
  srhbox2 = IupHbox(srframe3, srframe4, srframe5, NULL);
  IupSetAttribute(srhbox2, "GAP", "8");
  srhbox3 = IupHbox(srframe6, srframe7, NULL);
  IupSetAttribute(srhbox3, "GAP", "12");
  //IupSetAttribute(srhbox3, "MARGIN", "3x3");

  srvbox = IupVbox(srgridbox1, srhbox1, srhbox2, srhbox3, NULL);
  IupSetAttribute(srvbox, "GAP", "3");
  IupSetAttribute(srvbox, "ALIGNMENT", "ACENTER");

  // Dynamics of points
  Ihandle *id1, *id2, *id3, *id4, *id5, *id6, *id7, *id8, *id9, *id10, *id11,
    *id12, *id13;
  Ihandle *bd1, *bd2, *bd3, *bd4, *bd5, *bd6, *bd7, *bd8, *bd9, *bd10, *bd11,
    *bd12, *bd13, *dgridbox1, *mobilesBox, *blocksBox, *lawBox, *dvbox;

  id1 = IupLoadImage([[mb pathForResource: @"reference_system" ofType: @"tif" ] cString]);
  id2 = IupLoadImage([[mb pathForResource: @"mobiles" ofType: @"tif" ] cString]);
  id3 = IupLoadImage([[mb pathForResource: @"blocks" ofType: @"tif" ] cString]);
  id4 = IupLoadImage([[mb pathForResource: @"pulley" ofType: @"tif" ] cString]);
  id5 = IupLoadImage([[mb pathForResource: @"relation_accelerations" ofType: @"tif" ] cString]);
  id6 = IupLoadImage([[mb pathForResource: @"relative_motion" ofType: @"tif" ] cString]);
  id7 = IupLoadImage([[mb pathForResource: @"collision" ofType: @"tif" ] cString]);
  id8 = IupLoadImage([[mb pathForResource: @"law" ofType: @"tif" ] cString]);
  id9 = IupLoadImage([[mb pathForResource: @"power" ofType: @"tif" ] cString]);
  id10 = IupLoadImage([[mb pathForResource: @"springs" ofType: @"tif" ] cString]);
  id11 = IupLoadImage([[mb pathForResource: @"forces" ofType: @"tif" ] cString]);
  id12 = IupLoadImage([[mb pathForResource: @"frictions" ofType: @"tif" ] cString]);
  id13 = IupLoadImage([[mb pathForResource: @"contacts" ofType: @"tif" ] cString]);

  bd1 = IupFlatButton("_@FL_REF_SYS");
  IupSetAttributeHandle(bd1, "IMAGE", id1);
  IupSetAttribute(bd1, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd1, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bd1, "TAG", 100);
  bd2 = IupFlatButton(NULL);
  IupSetAttributeHandle(bd2, "IMAGE", id2);
  IupSetAttribute(bd2, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd2, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bd2, "TAG", 101);
  bd3 = IupFlatButton(NULL);
  IupSetAttributeHandle(bd3, "IMAGE", id3);
  IupSetAttribute(bd3, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd3, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bd3, "TAG", 104);
  bd4 = IupFlatButton("_@FL_PULLEY");
  IupSetAttributeHandle(bd4, "IMAGE", id4);
  IupSetAttribute(bd4, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd4, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bd4, "TAG", 108);
  bd5 = IupFlatButton("_@FL_RELATION_ACCELERATIONS");
  IupSetAttributeHandle(bd5, "IMAGE", id5);
  IupSetAttribute(bd5, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd5, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bd5, "TAG", 137);
  bd6 = IupFlatButton("_@FL_RELATIVE_MOTION");
  IupSetAttributeHandle(bd6, "IMAGE", id6);
  IupSetAttribute(bd6, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd6, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bd6, "TAG", 143);
  bd7 = IupFlatButton("_@FL_COLLISION");
  IupSetAttributeHandle(bd7, "IMAGE", id7);
  IupSetAttribute(bd7, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd7, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bd7, "TAG", 138);
  bd8 = IupFlatButton(NULL);
  IupSetAttributeHandle(bd8, "IMAGE", id8);
  IupSetAttribute(bd8, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd8, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bd8, "TAG", 139);
  bd9 = IupFlatButton("_@FL_POWER");
  IupSetAttributeHandle(bd9, "IMAGE", id9);
  IupSetAttribute(bd9, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd9, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bd9, "TAG", 141);
  bd10 = IupFlatButton(NULL);
  IupSetAttributeHandle(bd10, "IMAGE", id10);
  IupSetAttribute(bd10, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd10, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bd10, "TAG", 133);
  bd11 = IupFlatButton(NULL);
  IupSetAttributeHandle(bd11, "IMAGE", id11);
  IupSetAttribute(bd11, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd11, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bd11, "TAG", 109);
  bd12 = IupFlatButton(NULL);
  IupSetAttributeHandle(bd12, "IMAGE", id12);
  IupSetAttribute(bd12, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd12, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bd12, "TAG", 117);
  bd13 = IupFlatButton(NULL);
  IupSetAttributeHandle(bd13, "IMAGE", id13);
  IupSetAttribute(bd13, "IMAGEPOSITION", "TOP");
  IupSetCallback(bd13, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bd13, "TAG", 125);

  mobilesBox = IupVbox(bd2, IupLabel("_@FL_MOBILES"), NULL);
  IupSetAttribute(mobilesBox, "ALIGNMENT", "ACENTER");
  blocksBox = IupVbox(bd3, IupLabel("_@FL_BLOCKS"), NULL);
  IupSetAttribute(blocksBox, "ALIGNMENT", "ACENTER");
  lawBox = IupVbox(bd8, IupLabel("_@FL_LAW"), NULL);
  IupSetAttribute(lawBox, "ALIGNMENT", "ACENTER");

  dgridbox1 = IupGridBox(bd1, mobilesBox, blocksBox, bd4,
			 bd5, bd6, bd7, lawBox, NULL);
  IupSetAttribute(dgridbox1, "NUMDIV", "4");
  IupSetAttribute(dgridbox1, "GAPCOL", "5");
  IupSetAttribute(dgridbox1, "ALIGNMENTCOL", "ACENTER");
  IupSetAttribute(dgridbox1, "SIZELIN", "0");
  //IupSetAttribute(dgridbox1, "NORMALIZESIZE", "YES");

  Ihandle *dframe1, *dframe2, *dframe3, *dframe4, *dhbox1, *dhbox2;

  dframe1 = IupFrame(bd10);
  IupSetStrf(dframe1, "TITLE", "_@FL_SPRINGS");
  dframe2 = IupFrame(bd11);
  IupSetStrf(dframe2, "TITLE", "_@FL_FORCES");
  dframe3 = IupFrame(bd12);
  IupSetStrf(dframe3, "TITLE", "_@FL_FRICTIONS");
  dframe4 = IupFrame(bd13);
  IupSetStrf(dframe4, "TITLE", "_@FL_CONTACTS");

  dhbox1 = IupHbox(bd9, IupFill(), dframe1, NULL);
  IupSetAttribute(dhbox1, "GAP", "5");
  IupSetAttribute(dhbox1, "MARGIN", "3x0");
  dhbox2 = IupHbox(dframe2, dframe3, dframe4, NULL);
  IupSetAttribute(dhbox2, "GAP", "5");

  dvbox = IupVbox(dgridbox1, dhbox1, dhbox2, NULL);
  IupSetAttribute(dvbox, "GAP", "3");

  // Circular Dynamics of points
  Ihandle *idc1, *idc2, *idc3, *idc4, *idc5, *idc6, *idc7, *idc8, *idc9,
    *idc10, *idc11, *idc12, *idc13, *idc14, *idc15, *idc16, *idc17, *idc18,
    *idc19, *idc20, *idc21, *idc22, *idc23, *idc24, *idc25, *idc26;
  Ihandle *bdc1, *bdc2, *bdc3, *bdc4, *bdc5, *bdc6, *bdc7, *bdc8, *bdc9,
    *bdc10, *bdc11, *bdc12, *bdc13, *bdc14, *bdc15, *bdc16, *bdc17, *bdc18,
    *bdc19, *bdc20, *bdc21, *bdc22, *bdc23, *bdc24, *bdc25, *bdc26,
    *dcgridbox1, *dcvbox;

  idc1 = IupLoadImage([[mb pathForResource: @"reference_system" ofType: @"tif" ] cString]);
  idc2 = IupLoadImage([[mb pathForResource: @"mass_rest" ofType: @"tif" ] cString]);
  idc3 = IupLoadImage([[mb pathForResource: @"mobile_linear" ofType: @"tif" ] cString]);
  idc4 = IupLoadImage([[mb pathForResource: @"mobile_circular_b" ofType: @"tif" ] cString]);
  idc5 = IupLoadImage([[mb pathForResource: @"mobile_polar_b" ofType: @"tif" ] cString]);
  idc6 = IupLoadImage([[mb pathForResource: @"mobile_perpendicular" ofType: @"tif" ] cString]);
  idc7 = IupLoadImage([[mb pathForResource: @"energy" ofType: @"tif" ] cString]);
  idc8 = IupLoadImage([[mb pathForResource: @"momentum_angular" ofType: @"tif" ] cString]);
  idc9 = IupLoadImage([[mb pathForResource: @"momentum_linear" ofType: @"tif" ] cString]);
  idc10 = IupLoadImage([[mb pathForResource: @"power" ofType: @"tif" ] cString]);
  idc11 = IupLoadImage([[mb pathForResource: @"initial_system" ofType: @"tif" ] cString]);
  idc12 = IupLoadImage([[mb pathForResource: @"final_system" ofType: @"tif" ] cString]);
  idc13 = IupLoadImage([[mb pathForResource: @"relation_angles" ofType: @"tif" ] cString]);
  idc14 = IupLoadImage([[mb pathForResource: @"couple" ofType: @"tif" ] cString]);
  idc15 = IupLoadImage([[mb pathForResource: @"accelerations_triangle" ofType: @"tif" ] cString]);
  idc16 = IupLoadImage([[mb pathForResource: @"max_acceleration" ofType: @"tif" ] cString]);
  idc17 = IupLoadImage([[mb pathForResource: @"center_rotation" ofType: @"tif" ] cString]);
  idc18 = IupLoadImage([[mb pathForResource: @"angular_velocity" ofType: @"tif" ] cString]);
  idc19 = IupLoadImage([[mb pathForResource: @"centripetal_acceleration" ofType: @"tif" ] cString]);
  idc20 = IupLoadImage([[mb pathForResource: @"angular_acceleration" ofType: @"tif" ] cString]);
  idc21 = IupLoadImage([[mb pathForResource: @"inertia" ofType: @"tif" ] cString]);
  idc22 = IupLoadImage([[mb pathForResource: @"absolute_velocity" ofType: @"tif" ] cString]);
  idc23 = IupLoadImage([[mb pathForResource: @"sine_angle" ofType: @"tif" ] cString]);
  idc24 = IupLoadImage([[mb pathForResource: @"springs" ofType: @"tif" ] cString]);
  idc25 = IupLoadImage([[mb pathForResource: @"forces" ofType: @"tif" ] cString]);
  idc26 = IupLoadImage([[mb pathForResource: @"frictions_b" ofType: @"tif" ] cString]);

  bdc1 = IupFlatButton("_@FL_REF_SYS");
  IupSetAttributeHandle(bdc1, "IMAGE", idc1);
  IupSetAttribute(bdc1, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc1, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc1, "TAG", 300);
  bdc2 = IupFlatButton("_@FL_MASS_REST");
  IupSetAttributeHandle(bdc2, "IMAGE", idc2);
  IupSetAttribute(bdc2, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc2, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc2, "TAG", 301);
  bdc3 = IupFlatButton("_@FL_LINEAR");
  IupSetAttributeHandle(bdc3, "IMAGE", idc3);
  IupSetAttribute(bdc3, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc3, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc3, "TAG", 302);
  bdc4 = IupFlatButton("_@FL_CIRCULAR");
  IupSetAttributeHandle(bdc4, "IMAGE", idc4);
  IupSetAttribute(bdc4, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc4, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc4, "TAG", 303);
  bdc5 = IupFlatButton("_@FL_POLAR");
  IupSetAttributeHandle(bdc5, "IMAGE", idc5);
  IupSetAttribute(bdc5, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc5, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc5, "TAG", 339);
  bdc6 = IupFlatButton("_@FL_PERPENDICULAR");
  IupSetAttributeHandle(bdc6, "IMAGE", idc6);
  IupSetAttribute(bdc6, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc6, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc6, "TAG", 304);
  bdc7 = IupFlatButton("_@FL_ENERGY");
  IupSetAttributeHandle(bdc7, "IMAGE", idc7);
  IupSetAttribute(bdc7, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc7, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc7, "TAG", 305);
  bdc8 = IupFlatButton("_@FL_ANG_MOMENTUM");
  IupSetAttributeHandle(bdc8, "IMAGE", idc8);
  IupSetAttribute(bdc8, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc8, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc8, "TAG", 340);
  bdc9 = IupFlatButton("_@FL_LIN_MOMENTUM");
  IupSetAttributeHandle(bdc9, "IMAGE", idc9);
  IupSetAttribute(bdc9, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc9, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc9, "TAG", 306);
  bdc10 = IupFlatButton("_@FL_POWER");
  IupSetAttributeHandle(bdc10, "IMAGE", idc10);
  IupSetAttribute(bdc10, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc10, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc10, "TAG", 307);
  bdc11 = IupFlatButton("_@FL_INITIAL_SYS");
  IupSetAttributeHandle(bdc11, "IMAGE", idc11);
  IupSetAttribute(bdc11, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc11, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc11, "TAG", 308);
  bdc12 = IupFlatButton("_@FL_FINAL_SYS");
  IupSetAttributeHandle(bdc12, "IMAGE", idc12);
  IupSetAttribute(bdc12, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc12, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc12, "TAG", 309);
  bdc13 = IupFlatButton("_@FL_ANGLES");
  IupSetAttributeHandle(bdc13, "IMAGE", idc13);
  IupSetAttribute(bdc13, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc13, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc13, "TAG", 314);
  bdc14 = IupFlatButton("_@FL_COUPLE");
  IupSetAttributeHandle(bdc14, "IMAGE", idc14);
  IupSetAttribute(bdc14, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc14, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc14, "TAG", 315);
  bdc15 = IupFlatButton("_@FL_TRIANGLE_FORCES");
  IupSetAttributeHandle(bdc15, "IMAGE", idc15);
  IupSetAttribute(bdc15, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc15, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc15, "TAG", 316);
  bdc16 = IupFlatButton("_@FL_MAX_ACCELERATION");
  IupSetAttributeHandle(bdc16, "IMAGE", idc16);
  IupSetAttribute(bdc16, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc16, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc16, "TAG", 338);
  bdc17 = IupFlatButton("_@FL_CENTER");
  IupSetAttributeHandle(bdc17, "IMAGE", idc17);
  IupSetAttribute(bdc17, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc17, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc17, "TAG", 334);
  bdc18 = IupFlatButton("_@FL_ANGULAR_VELOCITY");
  IupSetAttributeHandle(bdc18, "IMAGE", idc18);
  IupSetAttribute(bdc18, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc18, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc18, "TAG", 335);
  bdc19 = IupFlatButton("_@FL_CENTRIPETAL_ACCELERATION");
  IupSetAttributeHandle(bdc19, "IMAGE", idc19);
  IupSetAttribute(bdc19, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc19, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc19, "TAG", 336);
  bdc20 = IupFlatButton("_@FL_ANGULAR_ACCELERATION");
  IupSetAttributeHandle(bdc20, "IMAGE", idc20);
  IupSetAttribute(bdc20, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc20, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc20, "TAG", 337);
  bdc21 = IupFlatButton("_@FL_INERTIA");
  IupSetAttributeHandle(bdc21, "IMAGE", idc21);
  IupSetAttribute(bdc21, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc21, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc21, "TAG", 343);
  bdc22 = IupFlatButton("_@FL_ABSOLUTE_VELOCITY");
  IupSetAttributeHandle(bdc22, "IMAGE", idc22);
  IupSetAttribute(bdc22, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc22, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc22, "TAG", 344);
  bdc23 = IupFlatButton("_@FL_SINE");
  IupSetAttributeHandle(bdc23, "IMAGE", idc23);
  IupSetAttribute(bdc23, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc23, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bdc23, "TAG", 310);
  bdc24 = IupFlatButton(NULL);
  IupSetAttributeHandle(bdc24, "IMAGE", idc24);
  IupSetAttribute(bdc24, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc24, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bdc24, "TAG", 317);
  bdc25 = IupFlatButton(NULL);
  IupSetAttributeHandle(bdc25, "IMAGE", idc25);
  IupSetAttribute(bdc25, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc25, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bdc25, "TAG", 321);
  bdc26 = IupFlatButton(NULL);
  IupSetAttributeHandle(bdc26, "IMAGE", idc26);
  IupSetAttribute(bdc26, "IMAGEPOSITION", "TOP");
  IupSetCallback(bdc26, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bdc26, "TAG", 329);

  dcgridbox1 = IupGridBox(bdc1, bdc2, bdc3, bdc4, bdc5, bdc6, bdc7, bdc8, bdc9,
			  bdc10, bdc11, bdc12, bdc13, bdc14, bdc15, bdc16,
			  bdc17, bdc18, bdc19, bdc20, bdc21, bdc22, bdc23,
			  NULL);
  IupSetAttribute(dcgridbox1, "NUMDIV", "4");
  IupSetAttribute(dcgridbox1, "GAPCOL", "3");
  IupSetAttribute(dcgridbox1, "ALIGNMENTCOL", "ACENTER");
  IupSetAttribute(dcgridbox1, "SIZELIN", "1");
  //IupSetAttribute(dcgridbox1, "NORMALIZESIZE", "YES");

  Ihandle *dcframe1, *dcframe2, *dcframe3, *dchbox1;

  dcframe1 = IupFrame(bdc24);
  IupSetStrf(dcframe1, "TITLE", "_@FL_SPRINGS");
  dcframe2 = IupFrame(bdc25);
  IupSetStrf(dcframe2, "TITLE", "_@FL_FORCES");
  dcframe3 = IupFrame(bdc26);
  IupSetStrf(dcframe3, "TITLE", "_@FL_FRICTIONS");

  dchbox1 = IupHbox(dcframe2, dcframe3, NULL);
  IupSetAttribute(dchbox1, "GAP", "5");
  IupSetAttribute(dchbox1, "MARGIN", "3x0");

  dcvbox = IupVbox(dcgridbox1, dcframe1, dchbox1, NULL);
  IupSetAttribute(dcvbox, "GAP", "3");
  IupSetAttribute(dcvbox, "ALIGNMENT", "ACENTER");

  // Module Calorimetry
  Ihandle *ic1, *ic2, *ic3, *ic4, *ic5, *ic6, *ic7, *ic8, *ic9, *ic10, *ic11,
    *ic12, *ic13, *ic14, *ic15, *ic16;
  Ihandle *bc1, *bc2, *bc3, *bc4, *bc5, *bc6, *bc7, *bc8, *bc9, *bc10, *bc11,
    *bc12, *bc13, *bc14, *bc15, *bc16, *expansionBox, *changeBox, *cgridbox1;
  
  ic1 = IupLoadImage([[mb pathForResource: @"clock" ofType: @"tif" ] cString]);
  ic2 = IupLoadImage([[mb pathForResource: @"heat_in" ofType: @"tif" ] cString]);
  ic3 = IupLoadImage([[mb pathForResource: @"heat_flow_in" ofType: @"tif" ] cString]);
  ic4 = IupLoadImage([[mb pathForResource: @"heat_out" ofType: @"tif" ] cString]);
  ic5 = IupLoadImage([[mb pathForResource: @"heat_flow_out" ofType: @"tif" ] cString]);
  ic6 = IupLoadImage([[mb pathForResource: @"block_cal" ofType: @"tif" ] cString]);
  ic7 = IupLoadImage([[mb pathForResource: @"liquid" ofType: @"tif" ] cString]);
  ic8 = IupLoadImage([[mb pathForResource: @"gas" ofType: @"tif" ] cString]);
  ic9 = IupLoadImage([[mb pathForResource: @"expansion" ofType: @"tif" ] cString]);
  ic10 = IupLoadImage([[mb pathForResource: @"change_state" ofType: @"tif" ] cString]);
  ic11 = IupLoadImage([[mb pathForResource: @"calorimeter" ofType: @"tif" ] cString]);
  ic12 = IupLoadImage([[mb pathForResource: @"gas_p" ofType: @"tif" ] cString]);
  ic13 = IupLoadImage([[mb pathForResource: @"gas_t" ofType: @"tif" ] cString]);
  ic14 = IupLoadImage([[mb pathForResource: @"gas_v" ofType: @"tif" ] cString]);
  ic15 = IupLoadImage([[mb pathForResource: @"gas_pvt" ofType: @"tif" ] cString]);
  ic16 = IupLoadImage([[mb pathForResource: @"heat_exchanger" ofType: @"tif" ] cString]);

  bc1 = IupFlatButton("_@FL_TIME_LAB");
  IupSetAttributeHandle(bc1, "IMAGE", ic1);
  IupSetAttribute(bc1, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc1, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc1, "TAG", 150);
  bc2 = IupFlatButton("_@FL_HEAT_IN");
  IupSetAttributeHandle(bc2, "IMAGE", ic2);
  IupSetAttribute(bc2, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc2, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc2, "TAG", 151);
  bc3 = IupFlatButton("_@FL_HEAT_FLOW_IN");
  IupSetAttributeHandle(bc3, "IMAGE", ic3);
  IupSetAttribute(bc3, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc3, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc3, "TAG", 152);
  bc4 = IupFlatButton("_@FL_HEAT_OUT");
  IupSetAttributeHandle(bc4, "IMAGE", ic4);
  IupSetAttribute(bc4, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc4, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc4, "TAG", 153);
  bc5 = IupFlatButton("_@FL_HEAT_FLOW_OUT");
  IupSetAttributeHandle(bc5, "IMAGE", ic5);
  IupSetAttribute(bc5, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc5, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc5, "TAG", 154);
  bc6 = IupFlatButton("_@FL_BLOCK");
  IupSetAttributeHandle(bc6, "IMAGE", ic6);
  IupSetAttribute(bc6, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc6, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc6, "TAG", 155);
  bc7 = IupFlatButton("_@FL_LIQUID");
  IupSetAttributeHandle(bc7, "IMAGE", ic7);
  IupSetAttribute(bc7, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc7, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc7, "TAG", 156);
  bc8 = IupFlatButton("_@FL_GAS");
  IupSetAttributeHandle(bc8, "IMAGE", ic8);
  IupSetAttribute(bc8, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc8, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc8, "TAG", 169);
  bc9 = IupFlatButton(NULL);
  IupSetAttributeHandle(bc9, "IMAGE", ic9);
  IupSetAttribute(bc9, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc9, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bc9, "TAG", 600);
  bc10 = IupFlatButton(NULL);
  IupSetAttributeHandle(bc10, "IMAGE", ic10);
  IupSetAttribute(bc10, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc10, "FLAT_BUTTON_CB", (Icallback)clickImage_cb);
  IupSetInt(bc10, "TAG", 601);
  bc11 = IupFlatButton("_@FL_CALORIMETER");
  IupSetAttributeHandle(bc11, "IMAGE", ic11);
  IupSetAttribute(bc11, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc11, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc11, "TAG", 163);
  bc12 = IupFlatButton("Gas P");
  IupSetAttributeHandle(bc12, "IMAGE", ic12);
  IupSetAttribute(bc12, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc12, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc12, "TAG", 164);
  bc13 = IupFlatButton("Gas T");
  IupSetAttributeHandle(bc13, "IMAGE", ic13);
  IupSetAttribute(bc13, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc13, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc13, "TAG", 165);
  bc14 = IupFlatButton("Gas V");
  IupSetAttributeHandle(bc14, "IMAGE", ic14);
  IupSetAttribute(bc14, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc14, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc14, "TAG", 166);
  bc15 = IupFlatButton("G. PVT");
  IupSetAttributeHandle(bc15, "IMAGE", ic15);
  IupSetAttribute(bc15, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc15, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc15, "TAG", 167);
  bc16 = IupFlatButton("_@FL_EXCHANGER");
  IupSetAttributeHandle(bc16, "IMAGE", ic16);
  IupSetAttribute(bc16, "IMAGEPOSITION", "TOP");
  IupSetCallback(bc16, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bc16, "TAG", 168);

  expansionBox = IupVbox(bc9, IupLabel("_@FL_EXPANSION"), NULL);
  IupSetAttribute(expansionBox, "ALIGNMENT", "ACENTER");
  changeBox = IupVbox(bc10, IupLabel("_@FL_CHANGE"), NULL);
  IupSetAttribute(changeBox, "ALIGNMENT", "ACENTER");

  cgridbox1 = IupGridBox(bc1, bc2, bc3, bc4, bc5, bc6, bc7, bc8, expansionBox,
			 changeBox, bc11, bc12, bc13, bc14, bc15, bc16, NULL);
  IupSetAttribute(cgridbox1, "NUMDIV", "4");
  IupSetAttribute(cgridbox1, "GAPCOL", "5");
  IupSetAttribute(cgridbox1, "ALIGNMENTCOL", "ACENTER");
  IupSetAttribute(cgridbox1, "SIZELIN", "2");
  IupSetAttribute(cgridbox1, "NORMALIZESIZE", "YES");

  // Module Thermodynamics
  // Ihandle *it1, *it2, *it3, *it4, *it5, *it6, *it7, *it8, *it9, *it10,
  Ihandle *it2, *it3, *it4,
    *it11, *it12, *it13, *it14, *it15, *it16, *it17, *it18, *it19, *it20;
  // Ihandle *bt1, *bt2, *bt3, *bt4, *bt5, *bt6, *bt7, *bt8, *bt9, *bt10,
  Ihandle *bt2, *bt3, *bt4,
    *bt11, *bt12, *bt13, *bt14, *bt15, *bt16, *bt17, *bt18, *bt19, *bt20,
    *tgridbox1;
  
  // it1 = IupLoadImage([[mb pathForResource: @"clock" ofType: @"tif" ] cString]);
  it2 = IupLoadImage([[mb pathForResource: @"heat_in" ofType: @"tif" ] cString]);
  it3 = IupLoadImage([[mb pathForResource: @"work_machine" ofType: @"tif" ] cString]);
  it4 = IupLoadImage([[mb pathForResource: @"heat_out" ofType: @"tif" ] cString]);
  // it5 = IupLoadImage([[mb pathForResource: @"state" ofType: @"tif" ] cString]);
  // it6 = IupLoadImage([[mb pathForResource: @"state_x" ofType: @"tif" ] cString]);
  // it7 = IupLoadImage([[mb pathForResource: @"flow" ofType: @"tif" ] cString]);
  // it8 = IupLoadImage([[mb pathForResource: @"flow_x" ofType: @"tif" ] cString]);
  // it9 = IupLoadImage([[mb pathForResource: @"process_general" ofType: @"tif" ] cString]);
  // it10 = IupLoadImage([[mb pathForResource: @"process_ideal_gas" ofType: @"tif" ] cString]);
  it11 = IupLoadImage([[mb pathForResource: @"adiabatic_process" ofType: @"tif" ] cString]);
  it12 = IupLoadImage([[mb pathForResource: @"gas_v" ofType: @"tif" ] cString]);
  it13 = IupLoadImage([[mb pathForResource: @"gas_t" ofType: @"tif" ] cString]);
  it14 = IupLoadImage([[mb pathForResource: @"gas_p" ofType: @"tif" ] cString]);
  it15 = IupLoadImage([[mb pathForResource: @"sensible_heat" ofType: @"tif" ] cString]);
  it16 = IupLoadImage([[mb pathForResource: @"change_state_liquid_gas" ofType: @"tif" ] cString]);
  it17 = IupLoadImage([[mb pathForResource: @"heat_engine" ofType: @"tif" ] cString]);
  it18 = IupLoadImage([[mb pathForResource: @"refrigerator" ofType: @"tif" ] cString]);
  it19 = IupLoadImage([[mb pathForResource: @"heat_pump" ofType: @"tif" ] cString]);
  it20 = IupLoadImage([[mb pathForResource: @"gas_pvt" ofType: @"tif" ] cString]);

  /*bt1 = IupFlatButton("T. Lab.");
  IupSetAttributeHandle(bt1, "IMAGE", it1);
  IupSetAttribute(bt1, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt1, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt1, "TAG", 1);*/
  bt2 = IupFlatButton("_@FL_HEAT_IN");
  IupSetAttributeHandle(bt2, "IMAGE", it2);
  IupSetAttribute(bt2, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt2, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt2, "TAG", 2);
  bt3 = IupFlatButton("_@FL_WORK");
  IupSetAttributeHandle(bt3, "IMAGE", it3);
  IupSetAttribute(bt3, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt3, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt3, "TAG", 3);
  bt4 = IupFlatButton("_@FL_HEAT_OUT");
  IupSetAttributeHandle(bt4, "IMAGE", it4);
  IupSetAttribute(bt4, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt4, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt4, "TAG", 20);
  /*bt5 = IupFlatButton("State");
  IupSetAttributeHandle(bt5, "IMAGE", it5);
  IupSetAttribute(bt5, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt5, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt5, "TAG", 4);
  bt6 = IupFlatButton("State x");
  IupSetAttributeHandle(bt6, "IMAGE", it6);
  IupSetAttribute(bt6, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt6, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt6, "TAG", 5);
  bt7 = IupFlatButton("Flow");
  IupSetAttributeHandle(bt7, "IMAGE", it7);
  IupSetAttribute(bt7, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt7, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt7, "TAG", 6);
  bt8 = IupFlatButton("Flow x");
  IupSetAttributeHandle(bt8, "IMAGE", it8);
  IupSetAttribute(bt8, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt8, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt8, "TAG", 7);
  bt9 = IupFlatButton("Process");
  IupSetAttributeHandle(bt9, "IMAGE", it9);
  IupSetAttribute(bt9, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt9, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt9, "TAG", 8);
  bt10 = IupFlatButton("IG Proc.");
  IupSetAttributeHandle(bt10, "IMAGE", it10);
  IupSetAttribute(bt10, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt10, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt10, "TAG", 9);*/
  bt11 = IupFlatButton("_@FL_ADIABATIC_PROC");
  IupSetAttributeHandle(bt11, "IMAGE", it11);
  IupSetAttribute(bt11, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt11, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt11, "TAG", 10);
  bt12 = IupFlatButton("_@FL_ISOCHORIC_PROC");
  IupSetAttributeHandle(bt12, "IMAGE", it12);
  IupSetAttribute(bt12, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt12, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt12, "TAG", 11);
  bt13 = IupFlatButton("_@FL_ISOTHERMIC_PROC");
  IupSetAttributeHandle(bt13, "IMAGE", it13);
  IupSetAttribute(bt13, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt13, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt13, "TAG", 12);
  bt14 = IupFlatButton("_@FL_ISOBARIC_PROC");
  IupSetAttributeHandle(bt14, "IMAGE", it14);
  IupSetAttribute(bt14, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt14, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt14, "TAG", 13);
  bt15 = IupFlatButton("_@FL_SENSIBLE_HEAT");
  IupSetAttributeHandle(bt15, "IMAGE", it15);
  IupSetAttribute(bt15, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt15, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt15, "TAG", 14);
  bt16 = IupFlatButton("_@FL_VAPORIZATION_HEAT");
  IupSetAttributeHandle(bt16, "IMAGE", it16);
  IupSetAttribute(bt16, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt16, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt16, "TAG", 15);
  bt17 = IupFlatButton("_@FL_HEAT_ENGINE");
  IupSetAttributeHandle(bt17, "IMAGE", it17);
  IupSetAttribute(bt17, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt17, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt17, "TAG", 21);
  bt18 = IupFlatButton("_@FL_REFRIGERATOR");
  IupSetAttributeHandle(bt18, "IMAGE", it18);
  IupSetAttribute(bt18, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt18, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt18, "TAG", 22);
  bt19 = IupFlatButton("_@FL_HEAT_PUMP");
  IupSetAttributeHandle(bt19, "IMAGE", it19);
  IupSetAttribute(bt19, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt19, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt19, "TAG", 23);
  bt20 = IupFlatButton("G. PVT");
  IupSetAttributeHandle(bt20, "IMAGE", it20);
  IupSetAttribute(bt20, "IMAGEPOSITION", "TOP");
  IupSetCallback(bt20, "FLAT_ACTION", (Icallback)clickElement_cb);
  IupSetInt(bt20, "TAG", 24);

  //tgridbox1 = IupGridBox(bt1, bt2, bt3, bt4, bt5, bt6, bt7, bt8, bt9, bt10,
  tgridbox1 = IupGridBox(bt2, bt3, bt4,
  			 bt11, bt12, bt13, bt14, bt15, bt16, bt17, bt18, bt19,
  			 bt20, NULL);
  IupSetAttribute(tgridbox1, "NUMDIV", "4");
  IupSetAttribute(tgridbox1, "GAPCOL", "5");
  IupSetAttribute(tgridbox1, "ALIGNMENTCOL", "ACENTER");
  IupSetAttribute(tgridbox1, "SIZELIN", "2");
  IupSetAttribute(tgridbox1, "NORMALIZESIZE", "YES");

  /////////////////////////////////////////////
  
  // Set names
  Ihandle *bgb1, *bgb2, *bgb3, *bgb4, *srscroll, *bgb5, *bgb6, *dcscroll,
    *bgb7, *bgb8;
  bgb1 = IupBackgroundBox(kgridbox1);
  bgb2 = IupBackgroundBox(kgridbox2);
  bgb3 = IupBackgroundBox(svbox);
  bgb4 = IupBackgroundBox(srvbox);
  bgb5 = IupBackgroundBox(dvbox);
  bgb6 = IupBackgroundBox(dcvbox);
  bgb7 = IupBackgroundBox(cgridbox1);
  bgb8 = IupBackgroundBox(tgridbox1);

  srscroll = IupScrollBox(bgb4);
  IupSetAttribute(srscroll, "RASTERSIZE", "278x250");
  IupSetAttribute(srscroll, "EXPAND", "VERTICAL");

  dcscroll = IupScrollBox(bgb6);
  IupSetAttribute(dcscroll, "RASTERSIZE", "278x250");
  IupSetAttribute(dcscroll, "EXPAND", "VERTICAL");
  
  IupSetHandle("FLKinematics", bgb1);
  IupSetHandle("FLKinematicsCircularMotion", bgb2);
  IupSetHandle("FLStatics", bgb3);
  IupSetHandle("FLStaticsRigidBodies", srscroll);
  IupSetHandle("FLDynamics", bgb5);
  IupSetHandle("FLDynamicsCircularMotion", dcscroll);
  IupSetHandle("FLCalorimetry", bgb7);
  IupSetHandle("FLThermodynamics", bgb8);

  // Units selector
  si = IupToggle("SI", NULL);
  IupSetCallback(si, "ACTION", (Icallback)selectUnits_cb);
  english = IupToggle("_@FL_ENGLISH", NULL);
  IupSetCallback(english, "ACTION", (Icallback)selectUnits_cb);
  radio = IupRadio(IupHbox(si, english, NULL));
  IupSetAttribute(radio, "NAME", "UNITS_RADIO");

  // List to select the module
  list = IupList(NULL);
  IupSetCallback(list, "ACTION", (Icallback)dropdown_cb);
  IupSetAttribute(list, "DROPDOWN", "YES");
  IupSetStrf(list, "1", "_@FL_MODULE_A");
  IupSetStrf(list, "2", "_@FL_MODULE_B");
  IupSetStrf(list, "3", "_@FL_MODULE_C");
  IupSetStrf(list, "4", "_@FL_MODULE_D");
  IupSetStrf(list, "5", "_@FL_MODULE_E");
  IupSetStrf(list, "6", "_@FL_MODULE_F");
  IupSetStrf(list, "7", "_@FL_MODULE_G");
  IupSetStrf(list, "8", "_@FL_MODULE_H");
  IupSetAttribute(list, "VALUE", "1");

  // Z box
  modbox = IupZbox(bgb1, bgb2, bgb3, srscroll, bgb5, dcscroll, bgb7, bgb8,
		   NULL);
  frame = IupFrame(modbox);
  IupSetAttribute(frame, "SUNKEN", "YES");

  //Matrix
  matrix = IupMatrix("actionTable_cb");
  IupSetCallback(matrix, "VALUE_EDIT_CB", (Icallback)editTable_cb);
  IupSetCallback(matrix, "EDITION_CB", (Icallback)editionTable_cb);
  IupSetCallback(matrix, "CLICK_CB", (Icallback)clickTable_cb);
  IupSetStrf(matrix, "0:1", "_@FL_DATA");
  IupSetStrf(matrix, "0:2", "_@FL_VALUE");
  IupSetAttribute(matrix, "NUMCOL", "2");
  IupSetAttribute(matrix, "NUMLIN", "5");
  IupSetAttribute(matrix, "ALIGNMENT1", "ALEFT");
  IupSetAttribute(matrix, "ALIGNMENT2", "ALEFT");
  IupSetAttribute(matrix, "WIDTH1", "50");
  IupSetAttribute(matrix, "WIDTH2", "80");
  IupSetAttribute(matrix, "SIZE", "150x");
  IupSetAttribute(matrix, "EXPAND", "VERTICAL");
  
  // Chalkboard
  int x, y;
  Ihandle *buttonCell;

  // Set the user preferences for the width and height of the chalkboard.
  chalkBoard = IupGridBox(NULL);
  width = IupConfigGetVariableIntDef(config, "MainWindow", "widthChalkBoard", 26);
  height = IupConfigGetVariableIntDef(config, "MainWindow", "heightChalkBoard", 18);

  // Add the cells for the chalkboard.
  for (y = 1; y <= height; y = y + 1)
    {
      for (x = 0; x < width; x = x + 1)
        {
	  buttonCell = IupFlatButton("");
	  IupSetAttribute(buttonCell, "RASTERSIZE", "50x50");
	  IupSetInt(buttonCell, "TAG", 0);
	  //IupSetAttribute(buttonCell, "BGCOLOR", "0 0 0");
	  //IupSetAttribute(buttonCell, "BORDER", "YES");
	  //IupSetAttribute(buttonCell, "BORDERWIDTH", "0");
	  //IupSetAttribute(buttonCell, "BORDERCOLOR", "0 0 0");
	  //IupSetAttribute(buttonCell, "BORDERHLCOLOR", "255 0 128");
	  IupSetCallback(buttonCell, "FLAT_ACTION", (Icallback)clickCell_cb);
	  IupAppend(chalkBoard, buttonCell);
        }
    }

  IupSetAttribute(chalkBoard, "NUMDIV", "26");

  scroll = IupScrollBox(chalkBoard);
  IupSetAttribute(scroll, "RASTERSIZE", "500x150");
  IupSetAttribute(scroll, "BGCOLOR", "0 0 0");
  IupSetAttribute(scroll, "BORDER", "YES");

  hbox1 = IupHbox(btnSolve, btnClean, NULL);
  IupSetAttribute(hbox1, "NGAP", "10");
  vbox1 = IupVbox(list, radio, frame, matrix, NULL);
  IupSetAttribute(vbox1, "NGAP", "10");
  vbox2 = IupVbox(hbox1, scroll, toggle, mline, NULL);
  IupSetAttribute(vbox2, "NGAP", "10");
  hbox2 = IupHbox(vbox1, vbox2, NULL);
  IupSetAttribute(hbox2, "NGAP", "20");
  IupSetAttribute(hbox2, "NMARGIN", "10x10");

  // Menu
  Ihandle *dlgicon, *menu, *sub1, *item1, *item2, *item3;

  item1 = IupItem("_@FL_MENU_ABOUT", NULL);
  IupSetAttribute(item1, "HIDEMARK", "YES");
  IupSetCallback(item1, "ACTION", (Icallback)about_cb);
  item2 = IupItem("_@FL_MENU_PREFERENCES", NULL);
  IupSetAttribute(item2, "HIDEMARK", "YES");
  IupSetCallback(item2, "ACTION", (Icallback)preferences_cb);
  item3 = IupItem("_@FL_MENU_QUIT", NULL);
  IupSetAttribute(item3, "HIDEMARK", "YES");
  IupSetCallback(item3, "ACTION", (Icallback)exit_cb);

  sub1 = IupMenu(item1, item2, item3, NULL);

  menu = IupMenu(IupSubmenu("_@FL_MENU_TITLE", sub1), NULL);

  dlg = IupDialog(hbox2);
  dlgicon = IupLoadImage([[mb pathForResource: @"FisicaLab" ofType: @"tif"]
			   cString]);
  IupSetHandle("FLIcon", dlgicon);
  IupSetAttributeHandle(dlg, "ICON", dlgicon);
  IupSetAttributeHandle(dlg, "MENU", menu);
  IupSetStrf(dlg, "TITLE", "_@FL_WINDOW_TITLE");
  IupSetHandle("FisicaLab", dlg);
  //IupSetAttribute(dlg, "RASTERSIZE", "950x670");

  IupSetGlobal("PARENTDIALOG", "FisicaLab");
  IupSetGlobal("ICON", "FLIcon");
  IupSetCallback(dlg, "CLOSE_CB", (Icallback)exit_cb);

  //IupShow(dlg);
  IupConfigDialogShow(config, dlg, "MainWindow");

  //IupSetAttribute(scroll, "POSY", "0.5");
  //IupSetAttribute(scroll, "SCROLLTO", "BOTTOM");
  //IupSetHandle("nameCell", buttonCell);
  //IupSetAttribute(scroll, "SCROLLTOCHILD", "nameCell");
  //IupSetAttributeHandle(scroll, "SCROLLTOCHILD_HANDLE", buttonCell);
  //IupRedraw(scroll, 1);
  //IupRefresh(scroll);

  if (!IupConfigGetVariableIntDef(config, "MainWindow", "HasStartedBefore", 0))
    {
      Ihandle *dlg2, *vbox, *box, *image, *link, *toggle;

      if ([[NSString stringWithCString: IupConfigGetVariableStrDef(config, "MainWindow", "Language", "ENGLISH")]
	  isEqualToString: @"ENGLISH"])
	{
	  image = IupLoadImage([[mb pathForResource: @"logoPanel" ofType: @"tif"
					inDirectory: nil forLocalization: @"English"]
				 cString]);
	}
      else
	{
	  image = IupLoadImage([[mb pathForResource: @"logoPanel" ofType: @"tif"
					inDirectory: nil forLocalization: @"Spanish"]
				 cString]);
	}

      link = IupLink ("https://www.gnu.org/software/fisicalab/",
		      "https://www.gnu.org/software/fisicalab/");

      toggle = IupToggle("_@FL_LOGO_PANEL", NULL);
      IupSetCallback(toggle, "ACTION", (Icallback)togglePanel_cb);

      vbox = IupVbox(IupFill(), link, toggle, NULL);
      IupSetAttribute(vbox, "ALIGNMENT", "ACENTER");
      IupSetAttribute(vbox, "MARGIN", "150x50");

      box = IupBackgroundBox(vbox);
      IupSetAttribute(box, "RASTERSIZE", "640x400");
      IupSetAttributeHandle(box, "BACKIMAGE", image);

      dlg2 = IupDialog(box);
      IupSetAttribute(dlg2, "ICON", "FLIcon");
      IupSetAttribute(dlg2, "RESIZE", "NO");
      IupSetAttribute(dlg2, "MINBOX", "NO");
      //IupSetAttribute(dlg2, "SIMULATEMODAL", "YES");
      IupShow(dlg2);
    }

  IupMainLoop();
  IupClose();

  return self;
}

@end
