/ src / hal / classicladder / edit_gtk.c
edit_gtk.c
  1  /* Classic Ladder Project */
  2  /* Copyright (C) 2001-2007 Marc Le Douarain */
  3  /* http://membres.lycos.fr/mavati/classicladder/ */
  4  /* http://www.sourceforge.net/projects/classicladder */
  5  /* May 2001 */
  6  /* --------------------------- */
  7  /* Editor - GTK interface part */
  8  /* --------------------------- */
  9  /* This library is free software; you can redistribute it and/or */
 10  /* modify it under the terms of the GNU Lesser General Public */
 11  /* License as published by the Free Software Foundation; either */
 12  /* version 2.1 of the License, or (at your option) any later version. */
 13  
 14  /* This library is distributed in the hope that it will be useful, */
 15  /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
 16  /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU */
 17  /* Lesser General Public License for more details. */
 18  
 19  /* You should have received a copy of the GNU Lesser General Public */
 20  /* License along with this library; if not, write to the Free Software */
 21  /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 22  
 23  #include <locale.h>
 24  #include <libintl.h>
 25  #define _(x) gettext(x)
 26  #include <gtk/gtk.h>
 27  #include <stdio.h>
 28  #include "classicladder.h"
 29  #include "global.h"
 30  #include "drawing.h"
 31  #include "edit.h"
 32  #include "classicladder_gtk.h"
 33  #include "edit_gtk.h"
 34  #include "editproperties_gtk.h"
 35  
 36  static GtkWidget *EditorButtonOk,*EditorButtonCancel;
 37  static GtkWidget *EditorButtonAdd,*EditorButtonIns,*EditorButtonDel;
 38  static GtkWidget *EditorButtonModify;
 39  
 40  #define NBR_ELE_IN_TOOLBAR 50
 41  #define NBR_ELE_TOOLBAR_Y_MAX 15 // used for each GtkTable
 42  #define NBR_ELE_TOOLBAR_X_MAX 4
 43  static GtkWidget * ToolbarBtnRadio[ NBR_ELE_IN_TOOLBAR ];
 44  static GtkWidget * ToolbarImage[ NBR_ELE_IN_TOOLBAR ];
 45  static GdkPixmap * ToolbarPixmap[ NBR_ELE_IN_TOOLBAR ];
 46  #define NUM_TOOLBAR_FOR_RUNGS 0
 47  #define NUM_TOOLBAR_FOR_SEQ 1
 48  static GtkWidget * ToolbarTable[ 2 ];
 49  static int NumWidgetEditPointer[ 2 ];
 50  GtkTooltips * TheTooltips;
 51  
 52  #define PIXELS_SIZE_IN_TOOLBAR 32
 53  
 54  static short int ToolBarElementsLadder[ ][NBR_ELE_TOOLBAR_X_MAX] =
 55              { {EDIT_POINTER , EDIT_ERASER, 0 , 0} ,
 56                {ELE_INPUT , ELE_INPUT_NOT , ELE_RISING_INPUT , ELE_FALLING_INPUT} ,
 57                {ELE_CONNECTION , EDIT_CNX_WITH_TOP, EDIT_LONG_CONNECTION , 0} ,
 58                {ELE_TIMER_IEC , ELE_COUNTER , ELE_COMPAR , 0} ,
 59  #ifdef OLD_TIMERS_MONOS_SUPPORT
 60                {ELE_TIMER , ELE_MONOSTABLE , 0 , 0} ,
 61  #endif
 62                {ELE_OUTPUT , ELE_OUTPUT_NOT, ELE_OUTPUT_SET , ELE_OUTPUT_RESET} ,
 63                {ELE_OUTPUT_JUMP, ELE_OUTPUT_CALL , ELE_OUTPUT_OPERATE , 0} ,
 64                {-1,-1}/*end*/ };
 65  char * ToolBarToolTipsTextLadder[ ][NBR_ELE_TOOLBAR_X_MAX] =
 66              { { "Object\nSelector", "Eraser", NULL, NULL },
 67                { "N.O. Input", "N.C. Input", "Rising Edge\n Input", "Falling Edge\n Input" },
 68                { "Horizontal\nConnection", "Vertical\nConnection", "Long Horizontal\nConnection", NULL },
 69                { "Timer IEC Block", "Counter Block",  "Variable\nComparison", NULL },
 70  #ifdef OLD_TIMERS_MONOS_SUPPORT
 71                { "Old Timer Block", "Monostable Block", NULL, NULL },
 72  #endif
 73                { "N.O. Output", "N.C. Output", "Set Output", "Reset Output" },
 74                { "Jump Coil", "Call Coil", "Variable\nAssignment", NULL },
 75                { NULL, NULL, NULL, NULL } };
 76  
 77  
 78  #ifdef SEQUENTIAL_SUPPORT
 79  #include "drawing_sequential.h"
 80  #include "edit_sequential.h"
 81  static short int ToolBarElementsSequential[ ][NBR_ELE_TOOLBAR_X_MAX] =
 82              { {EDIT_POINTER , EDIT_ERASER , 0 , 0} ,
 83                {ELE_SEQ_STEP , EDIT_SEQ_INIT_STEP , 0 , 0} ,
 84                {ELE_SEQ_TRANSITION , EDIT_SEQ_STEP_AND_TRANS , 0 , 0} ,
 85                {EDIT_SEQ_START_MANY_TRANS , EDIT_SEQ_END_MANY_TRANS , 0 , 0} ,
 86                {EDIT_SEQ_START_MANY_STEPS , EDIT_SEQ_END_MANY_STEPS , 0 , 0} ,
 87                {EDIT_SEQ_LINK , 0 , 0 , 0} ,
 88                {ELE_SEQ_COMMENT , 0 , 0 , 0} ,
 89                {-1,-1}/*end*/ };
 90  char * ToolBarToolTipsTextSequential[ ][NBR_ELE_TOOLBAR_X_MAX] =
 91              { { "Current Object\nSelector", "Eraser", NULL, NULL },
 92                { "Step", NULL, NULL, NULL },
 93                { "Transition", NULL, NULL, NULL },
 94                { NULL, NULL, NULL, NULL },
 95                { NULL, NULL, NULL, NULL },
 96                { "Link", NULL, NULL, NULL },
 97                { "Comment", NULL, NULL, NULL },
 98                { NULL, NULL, NULL, NULL } };
 99  #endif
100  
101  GtkWidget *EditWindow;
102  
103  
104  void ButtonsForStart()
105  {
106  	int iCurrentLanguage = SectionArray[ InfosGene->CurrentSection ].Language;
107  	gtk_widget_hide (EditorButtonAdd);
108  	gtk_widget_hide (EditorButtonIns);
109  	gtk_widget_hide (EditorButtonDel);
110  	gtk_widget_hide (EditorButtonModify);
111  	gtk_widget_show (EditorButtonOk);
112  	gtk_widget_show (EditorButtonCancel);
113  	ShowPropertiesWindow( TRUE );
114  	// select directly the pointer in toolbar per default...
115  	EditDatas.NumElementSelectedInToolBar = EDIT_POINTER;
116  	// ...in rung toolbar
117  	if ( NumWidgetEditPointer[ NUM_TOOLBAR_FOR_RUNGS ]!=-1 )
118  	{
119  		gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ToolbarBtnRadio[ NumWidgetEditPointer[ NUM_TOOLBAR_FOR_RUNGS ] ]), TRUE );
120  		gtk_widget_set_sensitive( ToolbarTable[ NUM_TOOLBAR_FOR_RUNGS ], TRUE );
121  	}
122  	// ...in sequential toolbar
123  	if ( NumWidgetEditPointer[ NUM_TOOLBAR_FOR_SEQ ]!=-1 )
124  	{
125  		gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ToolbarBtnRadio[ NumWidgetEditPointer[ NUM_TOOLBAR_FOR_SEQ ] ]), TRUE );
126  		gtk_widget_set_sensitive( ToolbarTable[ NUM_TOOLBAR_FOR_SEQ ], TRUE );
127  	}
128  	MessageInStatusBar( iCurrentLanguage==SECTION_IN_LADDER?_("Current rung in edit mode..."):_("Edit mode...") );
129  }
130  void ButtonsForEnd( char ForRung )
131  {
132  	if ( ForRung )
133  	{
134  		gtk_widget_show (EditorButtonAdd);
135  		gtk_widget_show (EditorButtonIns);
136  		gtk_widget_show (EditorButtonDel);
137  		gtk_widget_set_sensitive( ToolbarTable[ NUM_TOOLBAR_FOR_RUNGS ], FALSE );
138  	}
139  	else
140  	{
141  		gtk_widget_hide (EditorButtonAdd);
142  		gtk_widget_hide (EditorButtonIns);
143  		gtk_widget_hide (EditorButtonDel);
144  		gtk_widget_set_sensitive( ToolbarTable[ NUM_TOOLBAR_FOR_SEQ ], FALSE );
145  	}
146  	gtk_widget_show (EditorButtonModify);
147  	gtk_widget_hide (EditorButtonOk);
148  	gtk_widget_hide (EditorButtonCancel);
149  	ShowPropertiesWindow( FALSE );
150  	MessageInStatusBar( "" );
151  }
152  
153  void EditorButtonsAccordingSectionType( )
154  {
155  	int iCurrentLanguage = SectionArray[ InfosGene->CurrentSection ].Language;
156  	// if under edit, cancel current operation
157  	if ( EditDatas.ModeEdit )
158  		ButtonCancelCurrentRung( );
159  #ifdef SEQUENTIAL_SUPPORT
160  	if ( iCurrentLanguage==SECTION_IN_SEQUENTIAL )
161  	{
162  		gtk_widget_hide( ToolbarTable[ NUM_TOOLBAR_FOR_RUNGS ] );
163  		gtk_widget_show( ToolbarTable[ NUM_TOOLBAR_FOR_SEQ ] );
164  	}
165      else
166  	{
167  		gtk_widget_hide( ToolbarTable[ NUM_TOOLBAR_FOR_SEQ ] );
168  		gtk_widget_show( ToolbarTable[ NUM_TOOLBAR_FOR_RUNGS ] );
169  	}
170  #endif
171  	MessageInStatusBar( "" );
172  }
173  
174  void ButtonAddRung()
175  {
176  	AddRung();
177  	ButtonsForStart();
178  }
179  void ButtonInsertRung()
180  {
181  	InsertRung();
182  	ButtonsForStart();
183  }
184  void ButtonDeleteCurrentRung()
185  {
186  	ShowConfirmationBox(_("Delete"),_("Do you really want to delete the current rung ?"),DeleteCurrentRung);
187  }
188  void ButtonModifyCurrentRung()
189  {
190  	int iCurrentLanguage = SectionArray[ InfosGene->CurrentSection ].Language;
191  	if ( iCurrentLanguage==SECTION_IN_LADDER )
192  	{
193  		ModifyCurrentRung();
194  		ButtonsForStart();
195  	}
196  #ifdef SEQUENTIAL_SUPPORT
197  	if ( iCurrentLanguage==SECTION_IN_SEQUENTIAL )
198  	{
199  		ModifyCurrentSeqPage();
200  		ButtonsForStart();
201  	}
202  #endif
203  }
204  void ButtonOkCurrentRung()
205  {
206  	int iCurrentLanguage = SectionArray[ InfosGene->CurrentSection ].Language;
207  	if ( iCurrentLanguage==SECTION_IN_LADDER )
208  		ApplyRungEdited();
209  #ifdef SEQUENTIAL_SUPPORT
210  	if ( iCurrentLanguage==SECTION_IN_SEQUENTIAL )
211  		ApplySeqPageEdited();
212  #endif
213  	ButtonsForEnd( iCurrentLanguage==SECTION_IN_LADDER );
214  }
215  void ButtonCancelCurrentRung()
216  {
217  	int iCurrentLanguage = SectionArray[ InfosGene->CurrentSection ].Language;
218  	if ( iCurrentLanguage==SECTION_IN_LADDER )
219  		CancelRungEdited();
220  #ifdef SEQUENTIAL_SUPPORT
221  	if ( iCurrentLanguage==SECTION_IN_SEQUENTIAL )
222  		CancelSeqPageEdited();
223  #endif
224  	ButtonsForEnd( iCurrentLanguage==SECTION_IN_LADDER );
225  }
226  
227  gint EditorWindowDeleteEvent( GtkWidget * widget, GdkEvent * event, gpointer data )
228  {
229  	gtk_widget_hide( EditWindow );
230  	// we do not want that the window be destroyed.
231  	return TRUE;
232  }
233  
234  void OpenEditWindow( void )
235  {
236  	if ( !GTK_WIDGET_VISIBLE( EditWindow ) )
237  	{
238  		gtk_widget_show (EditWindow);
239  #ifdef GTK2
240  		gtk_window_present( GTK_WINDOW(EditWindow) );
241  #endif
242  	}
243  	else
244  	{
245  		gtk_widget_hide( EditWindow );
246  	}
247  }
248  
249  void ButtonToolbarSignal( GtkWidget * widget, gpointer data )
250  {
251  	EditDatas.NumElementSelectedInToolBar = GPOINTER_TO_INT( data );
252  }
253  
254  void InitAllForToolbar( void )
255  {
256  	int Search = 0;
257  	for ( Search=0; Search<NBR_ELE_IN_TOOLBAR; Search++ )
258  	{
259  		ToolbarBtnRadio[ Search ] = NULL;
260  		ToolbarImage[ Search ] = NULL;
261  		ToolbarPixmap[ Search ] = NULL;
262  	}
263  	NumWidgetEditPointer[ NUM_TOOLBAR_FOR_RUNGS ] = -1;
264  	NumWidgetEditPointer[ NUM_TOOLBAR_FOR_SEQ ] = -1;
265  }
266  
267  void CreateOneToolbar( GtkWidget * Box, int NumTable, short int PtrOnToolBarElementsList[][NBR_ELE_TOOLBAR_X_MAX], char * PtrOnToolTipsText[][NBR_ELE_TOOLBAR_X_MAX] )
268  {
269  	int CurrentAvail = 0;
270  	while( ToolbarBtnRadio[ CurrentAvail ]!=NULL && CurrentAvail<NBR_ELE_IN_TOOLBAR )
271  		CurrentAvail++;
272  	if ( CurrentAvail<NBR_ELE_IN_TOOLBAR )
273  	{
274  		StrElement ToolBarEle;
275  		int ScanToolBarX,ScanToolBarY;
276  		GSList * PtrListRadiosBtn = NULL;
277  		ScanToolBarX = 0;
278  		ScanToolBarY = 0;
279  		ToolbarTable[ NumTable ] = gtk_table_new( NBR_ELE_TOOLBAR_X_MAX, NBR_ELE_TOOLBAR_Y_MAX, FALSE/*homogeneous*/ );
280  		gtk_box_pack_start (GTK_BOX(Box), ToolbarTable[ NumTable ], TRUE, TRUE, 0);
281  		do
282  		{
283  			ToolBarEle.Type = PtrOnToolBarElementsList[ScanToolBarY][ScanToolBarX];
284  			ToolBarEle.ConnectedWithTop = 0;
285  			if ( ToolBarEle.Type==EDIT_POINTER )
286  			{
287  				if ( PtrOnToolBarElementsList!=ToolBarElementsSequential )
288  					NumWidgetEditPointer[ NUM_TOOLBAR_FOR_RUNGS ] = CurrentAvail;
289  				else
290  					NumWidgetEditPointer[ NUM_TOOLBAR_FOR_SEQ ] = CurrentAvail;
291  			}
292  
293  			if ( ToolBarEle.Type!=0 )
294  			{
295  				GdkGC * gc = drawing_area->style->bg_gc[0];
296  				char * pHelpText = PtrOnToolTipsText[ ScanToolBarY ][ ScanToolBarX ];
297  				ToolbarPixmap[ CurrentAvail ] = gdk_pixmap_new( GDK_DRAWABLE(drawing_area->window), PIXELS_SIZE_IN_TOOLBAR, PIXELS_SIZE_IN_TOOLBAR, -1 );
298  				gdk_draw_rectangle (GDK_DRAWABLE(ToolbarPixmap[ CurrentAvail ]), gc, TRUE, 0, 0, PIXELS_SIZE_IN_TOOLBAR, PIXELS_SIZE_IN_TOOLBAR);
299  	
300  	#ifdef SEQUENTIAL_SUPPORT
301  				if ( PtrOnToolBarElementsList==ToolBarElementsSequential )
302  					DrawSeqElementForToolBar(ToolbarPixmap[ CurrentAvail ], 0, 0, PIXELS_SIZE_IN_TOOLBAR, ToolBarEle.Type );
303  				else
304  	#endif
305  					DrawElement(ToolbarPixmap[ CurrentAvail ], 0, 0, PIXELS_SIZE_IN_TOOLBAR, PIXELS_SIZE_IN_TOOLBAR, ToolBarEle, TRUE);
306  	
307  				ToolbarImage[ CurrentAvail ] = gtk_image_new_from_pixmap( ToolbarPixmap[ CurrentAvail ], NULL );
308  				ToolbarBtnRadio[ CurrentAvail ] = gtk_radio_button_new( PtrListRadiosBtn );
309  				PtrListRadiosBtn = gtk_radio_button_get_group (GTK_RADIO_BUTTON(ToolbarBtnRadio[ CurrentAvail ]));
310  				gtk_button_set_relief (GTK_BUTTON( ToolbarBtnRadio[ CurrentAvail ] ), GTK_RELIEF_NONE);
311  				gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON(ToolbarBtnRadio[ CurrentAvail ]), FALSE);
312  				gtk_container_add( GTK_CONTAINER( ToolbarBtnRadio[ CurrentAvail ] ), ToolbarImage[ CurrentAvail ] );
313  				gtk_widget_show( ToolbarImage[ CurrentAvail ] );
314  				gtk_table_attach( GTK_TABLE( ToolbarTable[ NumTable ] ), ToolbarBtnRadio[ CurrentAvail ], 
315  									ScanToolBarX, ScanToolBarX+1, ScanToolBarY, ScanToolBarY+1,
316  									0, 0, 0, 0 );
317  
318  				gtk_signal_connect( GTK_OBJECT (ToolbarBtnRadio[ CurrentAvail ]), "clicked", (GtkSignalFunc) ButtonToolbarSignal, GINT_TO_POINTER((int)ToolBarEle.Type) );
319  
320  				if (pHelpText!=NULL )
321  					gtk_tooltips_set_tip (TheTooltips, ToolbarBtnRadio[ CurrentAvail ], pHelpText, NULL);
322  
323  				gtk_widget_show( ToolbarBtnRadio[ CurrentAvail ] );
324  				CurrentAvail++;
325  			}//if ( ToolBarEle.Type!=0 )
326  
327  			ScanToolBarX++;
328  			if (ScanToolBarX>=NBR_ELE_TOOLBAR_X_MAX)
329  			{
330  				ScanToolBarX = 0;
331  				ScanToolBarY++;
332  			}
333  		}
334  		while( PtrOnToolBarElementsList[ScanToolBarY][ScanToolBarX]!=-1 );
335  	}
336  }
337  
338  
339  void EditorInitGtk()
340  {
341  	GtkWidget *vbox;
342  
343  	EditWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
344  	gtk_window_set_title ( GTK_WINDOW( EditWindow ), _("Editor"));
345  
346  	vbox = gtk_vbox_new (FALSE, 0);
347  	gtk_container_add (GTK_CONTAINER (EditWindow), vbox);
348  	gtk_widget_show (vbox);
349  
350  	EditorButtonAdd = gtk_button_new_with_label (_("Add"));
351  	gtk_box_pack_start (GTK_BOX (vbox), EditorButtonAdd, FALSE, FALSE, 0);
352  	gtk_signal_connect(GTK_OBJECT (EditorButtonAdd), "clicked",
353  						(GtkSignalFunc) ButtonAddRung, 0);
354  	gtk_widget_show (EditorButtonAdd);
355  	EditorButtonIns = gtk_button_new_with_label (_("Insert"));
356  	gtk_box_pack_start (GTK_BOX (vbox), EditorButtonIns, FALSE, FALSE, 0);
357  	gtk_signal_connect(GTK_OBJECT (EditorButtonIns), "clicked",
358  						(GtkSignalFunc) ButtonInsertRung, 0);
359  	gtk_widget_show (EditorButtonIns);
360  	EditorButtonDel = gtk_button_new_with_label (_("Delete"));
361  	gtk_box_pack_start (GTK_BOX (vbox), EditorButtonDel, FALSE, FALSE, 0);
362  	gtk_signal_connect(GTK_OBJECT (EditorButtonDel), "clicked",
363  						(GtkSignalFunc) ButtonDeleteCurrentRung, 0);
364  	gtk_widget_show (EditorButtonDel);
365  	EditorButtonModify = gtk_button_new_with_label (_("Modify"));
366  	gtk_box_pack_start (GTK_BOX (vbox), EditorButtonModify, FALSE, FALSE, 0);
367  	gtk_signal_connect(GTK_OBJECT (EditorButtonModify), "clicked",
368  						(GtkSignalFunc) ButtonModifyCurrentRung, 0);
369  	gtk_widget_show (EditorButtonModify);
370  	EditorButtonOk = gtk_button_new_with_label (_("Ok"));
371  	gtk_box_pack_start (GTK_BOX (vbox), EditorButtonOk, FALSE, FALSE, 0);
372  	gtk_signal_connect(GTK_OBJECT (EditorButtonOk), "clicked",
373  						(GtkSignalFunc) ButtonOkCurrentRung, 0);
374  	EditorButtonCancel = gtk_button_new_with_label (_("Cancel"));
375  	gtk_box_pack_start (GTK_BOX (vbox), EditorButtonCancel, FALSE, FALSE, 0);
376  	gtk_signal_connect(GTK_OBJECT (EditorButtonCancel), "clicked",
377  						(GtkSignalFunc) ButtonCancelCurrentRung, 0);
378  
379  	InitAllForToolbar( );
380  	TheTooltips = gtk_tooltips_new();
381  	/* Rungs elements toolbar */
382  	CreateOneToolbar( vbox, NUM_TOOLBAR_FOR_RUNGS, ToolBarElementsLadder, ToolBarToolTipsTextLadder );
383  	gtk_widget_set_sensitive( ToolbarTable[ NUM_TOOLBAR_FOR_RUNGS ], FALSE );
384  	gtk_widget_show( ToolbarTable[ NUM_TOOLBAR_FOR_RUNGS ] );
385  	/* Sequential elements toolbar */
386  #ifdef SEQUENTIAL_SUPPORT
387  	CreateOneToolbar( vbox, NUM_TOOLBAR_FOR_SEQ, ToolBarElementsSequential, ToolBarToolTipsTextSequential );
388  	gtk_widget_set_sensitive( ToolbarTable[ NUM_TOOLBAR_FOR_SEQ ], FALSE );
389  #endif
390  
391  	gtk_signal_connect( GTK_OBJECT(EditWindow), "delete_event",
392  		(GtkSignalFunc)EditorWindowDeleteEvent, 0 );
393  
394  	gtk_window_set_resizable( GTK_WINDOW( EditWindow ), FALSE );
395  //gtk_widget_show (EditWindow);
396  
397  	EditDatas.NumElementSelectedInToolBar = -1;
398  }
399