1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11
12 #include <sys/types.h>
13 #include <time.h>
14 #include <sys/stat.h>
15 #if defined(HAVE_UNISTD_H)
16 #include <unistd.h>
17 #endif
18 #include <string.h> // for strerror
19 #include <errno.h> // for errno
20 #include <Xm/CascadeB.h>
21 #include <Xm/DrawingA.h>
22 #include <Xm/Frame.h>
23 #include <Xm/Form.h>
24 #include <Xm/Label.h>
25 #include <Xm/List.h>
26 #include <Xm/PushB.h>
27 #include <Xm/RowColumn.h>
28 #include <Xm/ScrolledW.h>
29 #include <Xm/Separator.h>
30 #include <Xm/AtomMgr.h>
31 #if !defined(ibm6000)
32 #define class ____class
33 #define new ____new
34 #endif
35 #include <Xm/ScrolledWP.h>
36 #if !defined(ibm6000)
37 #undef class
38 #undef new
39 #endif
40 #include <Xm/ScrollBar.h>
41
42 #include <X11/cursorfont.h>
43
44
45 #include "../widgets/WorkspaceW.h"
46 #include "EditorWindow.h"
47 #include "Ark.h"
48 #include "ButtonInterface.h"
49 #include "ColormapNode.h"
50 #include "ImageNode.h"
51 #include "ConfigurationDialog.h"
52 #include "ControlPanel.h"
53 #include "EditorToolSelector.h"
54 #include "VPERoot.h"
55 #include "ErrorDialogManager.h"
56 #include "DXApplication.h"
57 #include "DeleteNodeCommand.h"
58 #include "Dictionary.h"
59 #include "DictionaryIterator.h"
60 #include "InteractorNode.h"
61 #include "InteractorInstance.h"
62 #include "Network.h"
63 #include "NoUndoEditorCommand.h"
64 #include "NoUndoDXAppCommand.h"
65 #include "NodeDefinition.h"
66 #include "Node.h"
67 #include "Parameter.h"
68 #include "StandIn.h"
69 #include "ArkStandIn.h"
70 #include "ToggleButtonInterface.h"
71 #include "ToolPanelCommand.h"
72 #include "PanelAccessManager.h"
73 #include "PanelGroupManager.h"
74 #include "CloseWindowCommand.h"
75 #include "List.h"
76 #include "ListIterator.h"
77 #include "ProcessGroupCreateDialog.h"
78 #include "ProcessGroupAssignDialog.h"
79 #include "ControlPanelGroupDialog.h"
80 #include "ControlPanelAccessDialog.h"
81 #include "CreateMacroDialog.h"
82 #include "WarningDialogManager.h"
83 #include "InfoDialogManager.h"
84 #include "FindToolDialog.h"
85 #include "GridDialog.h"
86 #include "DXStrings.h"
87 #include "MacroNode.h"
88 #include "MacroDefinition.h"
89 #include "MacroParameterDefinition.h"
90 #include "MacroParameterNode.h"
91 #include "DeferrableAction.h"
92 #include "QuestionDialogManager.h"
93 #include "Decorator.h"
94 #include "LabelDecorator.h"
95 #include "VPEAnnotator.h"
96 #include "DecoratorStyle.h"
97 #include "DecoratorInfo.h"
98 #include "PrintProgramDialog.h"
99 #include "TransferAccelerator.h"
100 #if WORKSPACE_PAGES
101 #include "PageGroupManager.h"
102 #include "AnnotationGroupManager.h"
103 #include "PageSelector.h"
104 #endif
105
106 #ifdef DXUI_DEVKIT
107 #include "SaveAsCCodeDialog.h"
108 #endif // DXUI_DEVKIT
109
110 #include "CascadeMenu.h"
111 #include "TransmitterNode.h"
112 #include "ReceiverNode.h"
113 #include "GlobalLocalNode.h"
114 #include "DXLInputNode.h"
115 #include "GraphLayout.h"
116 #include "UndoMove.h"
117 #include "UndoDeletion.h"
118 #include "UndoRepeatableTab.h"
119 #include "UndoAddArk.h"
120 #include "Stack.h"
121 #include "XHandler.h"
122
123 #ifndef FORGET_GETSET
124 #include "GetSetConversionDialog.h"
125 Command *EditorWindow::SelectedToGlobalCmd = NULL;
126 Command *EditorWindow::SelectedToLocalCmd = NULL;
127 GetSetConversionDialog *EditorWindow::GetSetDialog = NULL;
128 #endif
129
130 #ifdef DXD_WIN
131 #define unlink _unlink
132 #endif
133
134 //
135 // Transmitter/Receiver for the execution/loop sequence numbers
136 #define JAVA_SEQUENCE "java_sequence"
137
138 // If you change this, you break existing nets
139 #define JAVA_SEQ_PAGE "java tools"
140
141 #include "EWDefaultResources.h"
142
143 #define NET_ATOM "NET_CONTENTS"
144 #define CFG_ATOM "CFG_CONTENTS"
145
146 boolean EditorWindow::ClassInitialized = FALSE;
147
EditorWindow(boolean isAnchor,Network * network)148 EditorWindow::EditorWindow(boolean isAnchor, Network* network) :
149 DXWindow("editorWindow", isAnchor)
150 {
151 ASSERT(network);
152
153 //
154 // Save associated network and designate self as the editor
155 // for this network.
156 //
157 this->network = network;
158 this->initialNetwork = TRUE;
159 this->lastSelectedTransmitter = NULL;
160
161 ASSERT(this->network->editor == NUL(EditorWindow*));
162 this->network->editor = this;
163 this->network->showEditorMessages();
164
165 //
166 // The panel is visible initially.
167 //
168 this->panelVisible = TRUE;
169
170 //
171 // Initially set hit detection to FALSE. It's not saved in
172 // the net file currently.
173 //
174 this->hit_detection = FALSE;
175
176 //
177 // Set the origin flag
178 //
179 this->resetOrigin();
180
181 this->findToolDialog = NULL;
182 this->printProgramDialog = NULL;
183 this->saveAsCCodeDialog = NULL;
184 this->panelGroupDialog = NULL;
185 this->gridDialog = NULL;
186 this->processGroupCreateDialog = NULL;
187 this->processGroupAssignDialog = NULL;
188 this->createMacroDialog = NULL;
189 this->insertNetworkDialog = NULL;
190
191 //
192 // Initialize member data.
193 //
194 this->currentPanel = NUL(ControlPanel*);
195
196 this->fileMenu = NUL(Widget);
197 this->editMenu = NUL(Widget);
198 this->windowsMenu = NUL(Widget);
199 this->optionsMenu = NUL(Widget);
200
201 this->fileMenuPulldown = NUL(Widget);
202 this->editMenuPulldown = NUL(Widget);
203 this->windowsMenuPulldown = NUL(Widget);
204 this->optionsMenuPulldown = NUL(Widget);
205
206 this->newOption = NUL(CommandInterface*);
207 this->openOption = NUL(CommandInterface*);
208 this->loadMacroOption = NUL(CommandInterface*);
209 this->loadMDFOption = NUL(CommandInterface*);
210 this->saveOption = NUL(CommandInterface*);
211 this->saveAsOption = NUL(CommandInterface*);
212 this->settingsCascade = NULL;
213 this->saveCfgOption = NULL;
214 this->openCfgOption = NULL;
215 this->printProgramOption = NUL(CommandInterface*);
216 this->saveAsCCodeOption = NUL(CommandInterface*);
217 this->quitOption = NUL(CommandInterface*);
218 this->closeOption = NUL(CommandInterface*);
219
220 this->undoOption = NUL(CommandInterface*);
221 this->valuesOption = NUL(CommandInterface*);
222 this->findToolOption = NUL(CommandInterface*);
223 this->Ox = -1;
224 this->find_restore_page = NUL(char*);
225 #ifndef FORGET_GETSET
226 this->programVerifyCascade = NUL(CascadeMenu*);
227 #endif
228 this->editTabsCascade = NULL;
229 this->addInputTabOption = NUL(CommandInterface*);
230 this->removeInputTabOption = NUL(CommandInterface*);
231 this->editSelectCascade = NULL;
232 this->outputCacheabilityCascade = NULL;
233 this->editOutputCacheabilityCascade = NULL;
234 #if WORKSPACE_PAGES
235 this->pageCascade = NULL;
236 #endif
237 this->javaCascade = NULL;
238 this->deleteOption = NUL(CommandInterface*);
239 this->cutOption = NUL(CommandInterface*);
240 this->copyOption = NUL(CommandInterface*);
241 this->pasteOption = NUL(CommandInterface*);
242 this->macroNameOption = NUL(CommandInterface*);
243 this->reflowGraphOption = NUL(CommandInterface*);
244 this->createMacroOption = NULL;
245 this->insertNetworkOption = NUL(CommandInterface*);
246 this->addAnnotationOption = NUL(CommandInterface*);
247 this->createProcessGroupOption= NUL(CommandInterface*);
248 this->assignProcessGroupOption= NUL(CommandInterface*);
249 this->commentOption = NUL(CommandInterface*);
250
251 this->newControlPanelOption = NUL(CommandInterface*);
252 this->openControlPanelOption = NUL(CommandInterface*);
253 this->openAllControlPanelsOption = NUL(CommandInterface*);
254 this->openControlPanelByNameMenu = NULL;
255 this->openMacroOption = NUL(CommandInterface*);
256 this->openImageOption = NUL(CommandInterface*);
257 this->openColormapEditorOption = NUL(CommandInterface*);
258
259 this->toolPalettesOption = NUL(CommandInterface*);
260 this->panelGroupOption = NUL(CommandInterface*);
261 this->gridOption = NUL(CommandInterface*);
262
263 this->onVisualProgramOption = NUL(CommandInterface*);
264 this->messageWindowOption = NUL(CommandInterface*);
265 this->workSpace = NULL;
266 this->addingDecorators = NUL(List*);
267 this->pendingPaste = NUL(Network*);
268 this->copiedNet = NUL(char*);
269 this->copiedCfg = NUL(char*);
270
271 //
272 // Create the commands.
273 //
274
275 //
276 // File menu commands
277 //
278 this->closeCmd =
279 new CloseWindowCommand("close",this->commandScope,TRUE,this);
280
281 this->printProgramCmd =
282 new NoUndoEditorCommand
283 ("printProgram", this->commandScope, FALSE,
284 this, NoUndoEditorCommand::PrintProgram, NoUndoEditorCommand::Ignore);
285
286 #ifdef DXUI_DEVKIT
287 this->saveAsCCodeCmd =
288 new NoUndoEditorCommand
289 ("saveAsCCode", this->commandScope, FALSE,
290 this, NoUndoEditorCommand::SaveAsCCode, NoUndoEditorCommand::Ignore);
291 #else
292 this->saveAsCCodeCmd = NULL;
293 #endif
294
295 //
296 // Edit menu commands
297 //
298 this->undoCmd =
299 new NoUndoEditorCommand
300 ("undo", this->commandScope, FALSE,
301 this, NoUndoEditorCommand::Undo, NoUndoEditorCommand::Ignore);
302 this->valuesCmd =
303 new NoUndoEditorCommand
304 ("values", this->commandScope, FALSE,
305 this, NoUndoEditorCommand::ShowConfiguration,
306 NoUndoEditorCommand::Ignore);
307
308 this->findToolCmd =
309 new NoUndoEditorCommand
310 ("findTool", this->commandScope, FALSE,
311 this, NoUndoEditorCommand::OpenFindTool,
312 NoUndoEditorCommand::Ignore);
313
314 this->addInputTabCmd =
315 new NoUndoEditorCommand
316 ("addInputTab", this->commandScope, FALSE,
317 this, NoUndoEditorCommand::AddInputTab,
318 NoUndoEditorCommand::AffectsUndo|NoUndoEditorCommand::CanBeUndone);
319
320 this->removeInputTabCmd =
321 new NoUndoEditorCommand
322 ("removeInputTab", this->commandScope, FALSE,
323 this, NoUndoEditorCommand::RemoveInputTab,
324 NoUndoEditorCommand::AffectsUndo|NoUndoEditorCommand::CanBeUndone);
325
326 this->addOutputTabCmd =
327 new NoUndoEditorCommand
328 ("addOutputTab", this->commandScope, FALSE,
329 this, NoUndoEditorCommand::AddOutputTab,
330 NoUndoEditorCommand::AffectsUndo|NoUndoEditorCommand::CanBeUndone);
331
332 this->removeOutputTabCmd =
333 new NoUndoEditorCommand
334 ("removeOutputTab", this->commandScope, FALSE,
335 this, NoUndoEditorCommand::RemoveOutputTab,
336 NoUndoEditorCommand::AffectsUndo|NoUndoEditorCommand::CanBeUndone);
337
338 this->hideAllTabsCmd =
339 new NoUndoEditorCommand
340 ("hideAllTabs", this->commandScope, FALSE,
341 this, NoUndoEditorCommand::HideAllTabs);
342
343 this->revealAllTabsCmd =
344 new NoUndoEditorCommand
345 ("revealAllTabs", this->commandScope, FALSE,
346 this, NoUndoEditorCommand::RevealAllTabs);
347
348 #ifndef FORGET_GETSET
349 this->postGetSetCmd =
350 new NoUndoEditorCommand
351 ("postGetSet", this->commandScope, TRUE,
352 this, NoUndoEditorCommand::PostGetSet,
353 NoUndoEditorCommand::Ignore);
354 this->toLocalCmd =
355 new NoUndoEditorCommand
356 ("setToLocal", this->commandScope, FALSE,
357 this, NoUndoEditorCommand::SelectedToLocal);
358 this->toGlobalCmd =
359 new NoUndoEditorCommand
360 ("setToGlobal", this->commandScope, FALSE,
361 this, NoUndoEditorCommand::SelectedToGlobal);
362 #endif
363
364 this->deleteNodeCmd =
365 new DeleteNodeCommand
366 ("deleteNode", this->commandScope, FALSE, this);
367
368 this->cutNodeCmd =
369 new NoUndoEditorCommand
370 ("cutNode", this->commandScope, FALSE,
371 this, NoUndoEditorCommand::CutNode,
372 NoUndoEditorCommand::AffectsUndo|NoUndoEditorCommand::CanBeUndone);
373
374 this->copyNodeCmd =
375 new NoUndoEditorCommand
376 ("copyNode", this->commandScope, FALSE,
377 this, NoUndoEditorCommand::CopyNode,
378 NoUndoEditorCommand::Ignore);
379
380 this->pasteNodeCmd =
381 new NoUndoEditorCommand
382 ("pasteNode", this->commandScope, TRUE,
383 this, NoUndoEditorCommand::PasteNode);
384
385 this->selectAllNodeCmd =
386 new NoUndoEditorCommand
387 ("selectAllNode", this->commandScope, FALSE,
388 this, NoUndoEditorCommand::SelectAll,
389 NoUndoEditorCommand::Ignore);
390
391 this->selectConnectedNodeCmd =
392 new NoUndoEditorCommand
393 ("selectConnectedNode", this->commandScope, FALSE,
394 this, NoUndoEditorCommand::SelectConnected,
395 NoUndoEditorCommand::Ignore);
396
397 this->selectUnconnectedNodeCmd =
398 new NoUndoEditorCommand
399 ("selectUnconectedNode", this->commandScope, FALSE,
400 this, NoUndoEditorCommand::SelectUnconnected,
401 NoUndoEditorCommand::Ignore);
402
403 this->selectUpwardNodeCmd =
404 new NoUndoEditorCommand
405 ("selectUpwardNode", this->commandScope, FALSE,
406 this, NoUndoEditorCommand::SelectUpward,
407 NoUndoEditorCommand::Ignore);
408
409 this->selectDownwardNodeCmd =
410 new NoUndoEditorCommand
411 ("selectDownwardNode", this->commandScope, FALSE,
412 this, NoUndoEditorCommand::SelectDownward,
413 NoUndoEditorCommand::Ignore);
414
415 this->deselectAllNodeCmd =
416 new NoUndoEditorCommand
417 ("deselectAllNode", this->commandScope, FALSE,
418 this, NoUndoEditorCommand::DeselectAll,
419 NoUndoEditorCommand::Ignore);
420
421 this->selectUnselectedNodeCmd =
422 new NoUndoEditorCommand
423 ("selectUnselectedNode", this->commandScope, FALSE,
424 this, NoUndoEditorCommand::SelectUnselected,
425 NoUndoEditorCommand::Ignore);
426
427 this->showExecutedCmd =
428 new NoUndoEditorCommand
429 ("showExecuted", this->commandScope, FALSE,
430 this, NoUndoEditorCommand::ShowExecutedNodes,
431 NoUndoEditorCommand::Ignore);
432
433 #ifndef FORGET_GETSET
434 if (!EditorWindow::SelectedToGlobalCmd) {
435 EditorWindow::SelectedToGlobalCmd = new NoUndoEditorCommand
436 ("SelectedToGlobal", this->commandScope, FALSE,
437 this, NoUndoEditorCommand::ToGlobal);
438
439 EditorWindow::SelectedToLocalCmd = new NoUndoEditorCommand
440 ("SelectedToLocal", this->commandScope, FALSE,
441 this, NoUndoEditorCommand::ToLocal);
442 }
443 #endif
444
445 this->cacheAllOutputsCmd =
446 new NoUndoEditorCommand
447 ("cacheAllOutputsCmd", this->commandScope, TRUE,
448 this, NoUndoEditorCommand::SetOutputsFullyCached,
449 NoUndoEditorCommand::Ignore);
450 this->cacheLastOutputsCmd =
451 new NoUndoEditorCommand
452 ("cacheLastOutputsCmd", this->commandScope, TRUE,
453 this, NoUndoEditorCommand::SetOutputsCacheOnce,
454 NoUndoEditorCommand::Ignore);
455 this->cacheNoOutputsCmd =
456 new NoUndoEditorCommand
457 ("cacheNoOutputsCmd", this->commandScope, TRUE,
458 this, NoUndoEditorCommand::SetOutputsNotCached,
459 NoUndoEditorCommand::Ignore);
460
461 this->optimizeCacheabilityCmd =
462 new NoUndoEditorCommand
463 ("optimizeCacheabilityCmd", this->commandScope, TRUE,
464 this, NoUndoEditorCommand::OptimizeOutputCacheability,
465 NoUndoEditorCommand::Ignore);
466
467 this->showCacheAllOutputsCmd =
468 new NoUndoEditorCommand
469 ("showCacheAllOutputsCmd", this->commandScope, TRUE,
470 this, NoUndoEditorCommand::ShowOutputsFullyCached,
471 NoUndoEditorCommand::Ignore);
472 this->showCacheLastOutputsCmd =
473 new NoUndoEditorCommand
474 ("showCacheLastOutputsCmd", this->commandScope, TRUE,
475 this, NoUndoEditorCommand::ShowOutputsCacheOnce,
476 NoUndoEditorCommand::Ignore);
477 this->showCacheNoOutputsCmd =
478 new NoUndoEditorCommand
479 ("showCacheNoOutputsCmd", this->commandScope, TRUE,
480 this, NoUndoEditorCommand::ShowOutputsNotCached,
481 NoUndoEditorCommand::Ignore);
482
483
484 this->editMacroNameCmd =
485 new NoUndoEditorCommand
486 ("editMacroName", this->commandScope, TRUE,
487 this, NoUndoEditorCommand::EditMacroName);
488
489 this->editCommentCmd =
490 new NoUndoEditorCommand
491 ("editComment", this->commandScope, TRUE,
492 this, NoUndoEditorCommand::EditComment,
493 NoUndoEditorCommand::Ignore);
494
495 this->createProcessGroupCmd =
496 new NoUndoEditorCommand
497 ("createProcessGroup", this->commandScope, isAnchor,
498 this, NoUndoEditorCommand::CreateProcessGroup,
499 NoUndoEditorCommand::Ignore);
500
501 this->insertNetCmd =
502 new NoUndoEditorCommand
503 ("insertNet", this->commandScope, TRUE,
504 this, NoUndoEditorCommand::InsertNetwork);
505
506 this->addAnnotationCmd =
507 new NoUndoEditorCommand
508 ("addAnnotation", this->commandScope, TRUE,
509 this, NoUndoEditorCommand::AddAnnotation);
510
511 this->macroifyCmd =
512 new NoUndoEditorCommand
513 ("macroify", this->commandScope, FALSE,
514 this, NoUndoEditorCommand::Macroify);
515
516 #if WORKSPACE_PAGES
517 this->pagifyCmd =
518 new NoUndoEditorCommand
519 ("pagify", this->commandScope, TRUE,
520 this, NoUndoEditorCommand::Pagify);
521
522 this->pagifySelectedCmd =
523 new NoUndoEditorCommand
524 ("pagifySelected", this->commandScope, FALSE,
525 this, NoUndoEditorCommand::PagifySelected);
526
527 this->autoChopSelectedCmd =
528 new NoUndoEditorCommand
529 ("autoChopSelected", this->commandScope, FALSE,
530 this, NoUndoEditorCommand::AutoChopSelected);
531
532 this->autoFuseSelectedCmd =
533 new NoUndoEditorCommand
534 ("autoFuseSelected", this->commandScope, FALSE,
535 this, NoUndoEditorCommand::AutoFuseSelected);
536
537 this->deletePageCmd =
538 new NoUndoEditorCommand
539 ("deletePage", this->commandScope, FALSE,
540 this, NoUndoEditorCommand::DeletePage);
541
542 this->configurePageCmd =
543 new NoUndoEditorCommand
544 ("configurePage", this->commandScope, TRUE,
545 this, NoUndoEditorCommand::ConfigurePage,
546 NoUndoEditorCommand::Ignore);
547
548 this->moveSelectedCmd =
549 new NoUndoEditorCommand
550 ("moveSelectedNodes", this->commandScope, TRUE,
551 this, NoUndoEditorCommand::MoveSelected);
552 #endif
553
554 if (this->network->isMacro() == FALSE) {
555
556 this->javifyNetCmd = new NoUndoEditorCommand
557 ("javifyNetwork", this->commandScope, FALSE,
558 this, NoUndoEditorCommand::JavifyNetwork);
559 this->unjavifyNetCmd = new NoUndoEditorCommand
560 ("unJavifyNetwork", this->commandScope, TRUE,
561 this, NoUndoEditorCommand::UnjavifyNetwork);
562 } else {
563 this->javifyNetCmd = NUL(Command*);
564 this->unjavifyNetCmd = NUL(Command*);
565 }
566 this->reflowGraphCmd =
567 new NoUndoEditorCommand ("reflowGraph", this->commandScope, FALSE,
568 this, NoUndoEditorCommand::ReflowGraph,
569 NoUndoEditorCommand::AffectsUndo|NoUndoEditorCommand::CanBeUndone);
570
571 //
572 // Window's menu commands
573 //
574 this->openMacroCmd =
575 new NoUndoEditorCommand("openMacroCommand", this->commandScope,
576 FALSE,this, NoUndoEditorCommand::OpenSelectedMacros,
577 NoUndoEditorCommand::Ignore);
578
579 this->openColormapCmd =
580 new NoUndoEditorCommand("openColormapCmd",
581 this->commandScope,
582 FALSE,
583 this,
584 NoUndoEditorCommand::OpenSelectedColormaps,
585 NoUndoEditorCommand::Ignore);
586 this->openImageCmd =
587 new NoUndoEditorCommand("openImageCommand", this->commandScope,
588 FALSE,this,
589 NoUndoEditorCommand::OpenSelectedImageWindows,
590 NoUndoEditorCommand::Ignore);
591
592 this->newControlPanelCmd =
593 new NoUndoEditorCommand
594 ("newControlPanel", this->commandScope, TRUE,
595 this, NoUndoEditorCommand::NewControlPanel,
596 NoUndoEditorCommand::Ignore);
597
598 this->openControlPanelCmd =
599 new NoUndoEditorCommand
600 ("openControlPanel", this->commandScope, FALSE,
601 this, NoUndoEditorCommand::OpenControlPanel,
602 NoUndoEditorCommand::Ignore);
603
604 //
605 // Options's menu commands
606 //
607 this->toolPanelCmd =
608 new ToolPanelCommand
609 ("toolPalettes", this->commandScope, TRUE, this);
610
611 this->hitDetectionCmd =
612 new NoUndoEditorCommand
613 ("hitDetector", this->commandScope, TRUE,
614 this, NoUndoEditorCommand::HitDetection,
615 NoUndoEditorCommand::Ignore);
616
617 this->setPanelAccessCmd =
618 new NoUndoEditorCommand
619 ("setAccess", this->commandScope, FALSE,
620 this, NoUndoEditorCommand::SetCPAccess,
621 NoUndoEditorCommand::Ignore);
622
623 this->setPanelGroupCmd =
624 new NoUndoEditorCommand
625 ("setGroup", this->commandScope, FALSE,
626 this, NoUndoEditorCommand::SetPanelGroup,
627 NoUndoEditorCommand::Ignore);
628
629 this->gridCmd =
630 new NoUndoEditorCommand
631 ("grid", this->commandScope, TRUE,
632 this, NoUndoEditorCommand::OpenGrid,
633 NoUndoEditorCommand::Ignore);
634
635 this->deferrableCommandActivation = new DeferrableAction(
636 EditorWindow::SetCommandActivation,
637 (void*)this);
638
639 this->addInputTabCmd->autoActivate(this->removeInputTabCmd);
640 this->addOutputTabCmd->autoActivate(this->removeOutputTabCmd);
641 this->revealAllTabsCmd->autoActivate(this->hideAllTabsCmd);
642 this->hideAllTabsCmd->autoActivate(this->revealAllTabsCmd);
643
644 this->resetWindowTitle();
645
646 //
647 // List of executed nodes
648 //
649 this->executed_nodes = NUL(List*);
650 this->executing_node = NUL(Node*);
651 this->transmitters_added = FALSE;
652 this->errored_standins = NUL(List*);
653
654 //
655 // Graph layout
656 //
657 this->layout_controller = NULL;
658
659 //
660 // Undo list management
661 //
662 this->moving_many_standins = FALSE;
663 this->performing_undo = FALSE;
664 this->creating_new_network = FALSE;
665
666 // work around for a motif bug
667 this->pgKeyHandler = NUL(XHandler*);
668
669 //
670 // Install the default resources for THIS class (not the derived classes)
671 //
672 if (NOT EditorWindow::ClassInitialized)
673 {
674 ASSERT(theApplication);
675 EditorWindow::ClassInitialized = TRUE;
676 this->installDefaultResources(theApplication->getRootWidget());
677 }
678 }
679
680
~EditorWindow()681 EditorWindow::~EditorWindow()
682 {
683
684 //
685 // Delete the dialogs.
686 //
687 if(this->findToolDialog)
688 delete this->findToolDialog;
689 if(this->printProgramDialog)
690 delete this->printProgramDialog;
691 if(this->saveAsCCodeDialog)
692 delete this->saveAsCCodeDialog;
693 if(this->panelGroupDialog)
694 delete this->panelGroupDialog;
695 if(this->gridDialog)
696 delete this->gridDialog;
697 if(this->processGroupCreateDialog)
698 delete this->processGroupCreateDialog;
699 if(this->processGroupAssignDialog)
700 delete this->processGroupAssignDialog;
701 if(this->createMacroDialog)
702 delete this->createMacroDialog;
703 if(this->insertNetworkDialog)
704 delete this->insertNetworkDialog;
705
706 //
707 // File menu options
708 //
709 if (this->newOption) delete this->newOption;
710 if (this->openOption) delete this->openOption;
711 if (this->loadMacroOption) delete this->loadMacroOption;
712 if (this->loadMDFOption) delete this->loadMDFOption;
713 if (this->saveOption) delete this->saveOption;
714 if (this->saveAsOption) delete this->saveAsOption;
715 if (this->settingsCascade) delete this->settingsCascade;
716 if (this->saveCfgOption) delete this->saveCfgOption;
717 if (this->openCfgOption) delete this->openCfgOption;
718 if (this->printProgramOption) delete this->printProgramOption;
719 if (this->saveAsCCodeOption) delete this->saveAsCCodeOption;
720 if (this->quitOption) delete this->quitOption;
721 if (this->closeOption) delete this->closeOption;
722
723 //
724 // Edit menu options
725 //
726 if (this->undoOption) delete this->undoOption;
727 if (this->valuesOption) delete this->valuesOption;
728 if (this->findToolOption) delete this->findToolOption;
729 #ifndef FORGET_GETSET
730 if (this->programVerifyCascade) delete this->programVerifyCascade;
731 #endif
732 if (this->editTabsCascade) delete this->editTabsCascade;
733 //if (this->addInputTabOption) delete this->addInputTabOption;
734 //if (this->removeInputTabOption) delete this->removeInputTabOption;
735 if (this->editSelectCascade) delete this->editSelectCascade;
736 if (this->editOutputCacheabilityCascade) delete this->editOutputCacheabilityCascade;
737 if (this->outputCacheabilityCascade) delete this->outputCacheabilityCascade;
738 #if WORKSPACE_PAGES
739 if (this->pageCascade) delete this->pageCascade;
740 #endif
741 if (this->javaCascade) delete this->javaCascade;
742 if (this->deleteOption) delete this->deleteOption;
743 if (this->cutOption) delete this->cutOption;
744 if (this->copyOption) delete this->copyOption;
745 if (this->pasteOption) delete this->pasteOption;
746 if (this->macroNameOption) delete this->macroNameOption;
747 if (this->reflowGraphOption) delete this->reflowGraphOption;
748 if (this->createMacroOption) delete this->createMacroOption;
749 if (this->insertNetworkOption) delete this->insertNetworkOption;
750 if (this->addAnnotationOption) delete this->addAnnotationOption;
751 if (this->createProcessGroupOption) delete this->createProcessGroupOption;
752 if (this->commentOption) delete this->commentOption;
753
754
755 //
756 // Windows options
757 //
758 if (this->newControlPanelOption) delete this->newControlPanelOption;
759 if (this->openControlPanelOption) delete this->openControlPanelOption;
760 if (this->openAllControlPanelsOption) delete this->openAllControlPanelsOption;
761 if (this->openControlPanelByNameMenu) delete this->openControlPanelByNameMenu;
762 if (this->openMacroOption) delete this->openMacroOption;
763 if (this->openImageOption) delete this->openImageOption;
764 if (this->openColormapEditorOption) delete this->openColormapEditorOption;
765 if (this->messageWindowOption) delete this->messageWindowOption;
766
767 //
768 // Options options
769 //
770 if (this->toolPalettesOption) delete this->toolPalettesOption;
771 if (this->gridOption) delete this->gridOption;
772 if (this->panelGroupOption) delete this->panelGroupOption;
773 if (this->panelAccessOption) delete this->panelAccessOption;
774
775 if (this->onVisualProgramOption) delete this->onVisualProgramOption;
776
777 if (this->workSpace) delete this->workSpace;
778
779 //
780 // Delete the commands after the command interfaces.
781 //
782 delete this->toolPanelCmd;
783 delete this->hitDetectionCmd;
784 delete this->showExecutedCmd;
785 delete this->newControlPanelCmd;
786 delete this->openControlPanelCmd;
787 delete this->undoCmd;
788 delete this->valuesCmd;
789 delete this->addInputTabCmd;
790 delete this->removeInputTabCmd;
791 delete this->addOutputTabCmd;
792 delete this->removeOutputTabCmd;
793 delete this->hideAllTabsCmd;
794 delete this->revealAllTabsCmd;
795 #ifndef FORGET_GETSET
796 delete this->postGetSetCmd;
797 delete this->toLocalCmd;
798 delete this->toGlobalCmd;
799 #endif
800 delete this->deleteNodeCmd;
801 delete this->cutNodeCmd;
802 delete this->copyNodeCmd;
803 delete this->pasteNodeCmd;
804 delete this->selectAllNodeCmd;
805 delete this->selectConnectedNodeCmd;
806 delete this->selectUnconnectedNodeCmd;
807 delete this->selectUnselectedNodeCmd;
808 delete this->selectUpwardNodeCmd;
809 delete this->selectDownwardNodeCmd;
810 delete this->cacheAllOutputsCmd;
811 delete this->cacheLastOutputsCmd;
812 delete this->cacheNoOutputsCmd;
813 delete this->showCacheAllOutputsCmd;
814 delete this->showCacheLastOutputsCmd;
815 delete this->showCacheNoOutputsCmd;
816 delete this->optimizeCacheabilityCmd;
817 delete this->deselectAllNodeCmd;
818 delete this->insertNetCmd;
819 delete this->addAnnotationCmd;
820 delete this->macroifyCmd;
821 #if WORKSPACE_PAGES
822 delete this->pagifyCmd;
823 delete this->pagifySelectedCmd;
824 delete this->autoChopSelectedCmd;
825 delete this->autoFuseSelectedCmd;
826 delete this->deletePageCmd;
827 delete this->configurePageCmd;
828 delete this->moveSelectedCmd;
829 #endif
830 if (this->javifyNetCmd) delete this->javifyNetCmd;
831 if (this->unjavifyNetCmd) delete this->unjavifyNetCmd;
832 delete this->reflowGraphCmd;
833 delete this->editMacroNameCmd;
834 delete this->editCommentCmd;
835 delete this->findToolCmd;
836 delete this->gridCmd;
837 delete this->setPanelAccessCmd;
838 delete this->setPanelGroupCmd;
839 delete this->createProcessGroupCmd;
840 delete this->openImageCmd;
841 delete this->openColormapCmd;
842 delete this->openMacroCmd;
843 delete this->closeCmd;
844 delete this->printProgramCmd;
845 if (this->saveAsCCodeCmd) delete this->saveAsCCodeCmd;
846
847 this->network->editor = NUL(EditorWindow*);
848
849 delete this->deferrableCommandActivation;
850
851 //
852 // Delete the category/tool lists for this editor.
853 //
854 delete this->toolSelector;
855 #if WORKSPACE_PAGES
856 delete this->pageSelector;
857 #endif
858
859 if (this->addingDecorators) delete this->addingDecorators;
860 if (this->pendingPaste) delete this->pendingPaste;
861 if (this->copiedNet) delete this->copiedNet;
862 if (this->copiedCfg) delete this->copiedCfg;
863 if (this->executed_nodes) delete this->executed_nodes;
864 if (this->errored_standins) delete this->errored_standins;
865 if (this->layout_controller) delete this->layout_controller;
866 this->clearUndoList();
867
868 if (this->find_restore_page) delete this->find_restore_page;
869
870 if (this->pgKeyHandler) delete this->pgKeyHandler;;
871 }
872
873 //
874 // Install the default resources for this class.
875 //
installDefaultResources(Widget baseWidget)876 void EditorWindow::installDefaultResources(Widget baseWidget)
877 {
878 this->setDefaultResources(baseWidget, EditorWindow::DefaultResources);
879 this->DXWindow::installDefaultResources(baseWidget);
880 }
881
SetCommandActivation(void * editor,void * requestData)882 void EditorWindow::SetCommandActivation(void *editor, void *requestData)
883 {
884 ((EditorWindow*)editor)->setCommandActivation();
885 }
886 //
887 // De/Activate any commands that have to do with editing.
888 // Should be called when a node is added or deleted or there is a selection
889 // status change.
890 //
setCommandActivation()891 void EditorWindow::setCommandActivation()
892 {
893 int nselected;
894
895 int nodes = this->getNetwork()->getNodeCount();
896
897 int decors = 0;
898 int dselected = 0;
899 decors = this->getNetwork()->decoratorList.getSize();
900 ListIterator it;
901 Decorator *decor;
902 FOR_EACH_NETWORK_DECORATOR(this->getNetwork(),decor,it) {
903 if (decor->isSelected()) dselected++;
904 }
905
906 //
907 // Are execution results available?
908 //
909 if ((this->executed_nodes) && (this->executed_nodes->getSize())) {
910 this->showExecutedCmd->activate();
911 } else {
912 this->showExecutedCmd->deactivate();
913 }
914
915 //
916 // count the nodes in the current page
917 //
918 WorkSpace *current_ws = this->workSpace;
919 int page = this->workSpace->getCurrentPage();
920 if (page) current_ws = this->workSpace->getElement(page);
921 int nodes_in_current_page = 0;
922 Node *n;
923 ListIterator iterator;
924 FOR_EACH_NETWORK_NODE(this->network, n, iterator) {
925 StandIn* si = n->getStandIn();
926 if (!si) continue;
927 if (si->getWorkSpace() == current_ws)
928 nodes_in_current_page++;
929 }
930
931 //
932 // Is undo available? ...also sets button label
933 //
934 this->setUndoActivation();
935
936 //
937 // Handle commands that depend on whether there are nodes in the current page
938 //
939 if (nodes_in_current_page==0) {
940 this->reflowGraphCmd->deactivate();
941 } else {
942 this->reflowGraphCmd->activate();
943 }
944
945 //
946 // Handle commands that depend on whether there are nodes
947 //
948 if (nodes == 0) {
949 if (decors == 0)
950 this->selectAllNodeCmd->deactivate();
951 else
952 this->selectAllNodeCmd->activate();
953 this->findToolCmd->deactivate();
954 this->printProgramCmd->deactivate();
955 if (this->saveAsCCodeCmd)
956 this->saveAsCCodeCmd->deactivate();
957 nselected = 0;
958 this->outputCacheabilityCascade->deactivate();
959 } else {
960 this->selectAllNodeCmd->activate();
961 this->findToolCmd->activate();
962 this->printProgramCmd->activate();
963 if (this->saveAsCCodeCmd)
964 this->saveAsCCodeCmd->activate();
965 nselected = this->getNodeSelectionCount();
966 this->outputCacheabilityCascade->activate();
967 }
968
969 //
970 // Set Activation of commands that depend on whether or not the
971 // network is a macro.
972 // FIXME: should ASSERT(net), but just before 2.0 release we'll be
973 // VERY careful.
974 //
975 Network *net = this->getNetwork();
976 if ((nodes != 0) && net && !net->isMacro()) {
977 this->createProcessGroupCmd->activate();
978 } else {
979 this->createProcessGroupCmd->deactivate();
980 }
981
982 #ifndef FORGET_GETSET
983 EditorWindow *ew =
984 ((EditorWindow::GetSetDialog && EditorWindow::GetSetDialog->isManaged())?
985 EditorWindow::GetSetDialog->getActiveEditor():
986 NULL);
987 if ((EditorWindow::GetSetDialog) &&
988 (EditorWindow::GetSetDialog->isManaged()) && (!ew)) {
989 EditorWindow::GetSetDialog->setActiveEditor(this);
990 ew = EditorWindow::GetSetDialog->getActiveEditor();
991 }
992 #endif
993
994 //
995 // Handle commands that depend on whether there are populated pages
996 //
997 #if WORKSPACE_PAGES
998 if (this->pageSelector->getSize() > 1) {
999 this->deletePageCmd->activate();
1000 } else {
1001 // does it have a group record
1002 int page_num = this->workSpace->getCurrentPage();
1003 EditorWorkSpace* ews = this->workSpace;
1004 if (page_num)
1005 ews = (EditorWorkSpace*)this->workSpace->getElement(page_num);
1006 GroupRecord* grec = this->getGroupOfWorkSpace(ews);
1007 if (grec)
1008 this->deletePageCmd->activate();
1009 else
1010 this->deletePageCmd->deactivate();
1011 }
1012 #endif
1013
1014 //
1015 // command depends on whether selected nodes are pagifiable
1016 //
1017 boolean mscmd_activate = FALSE;
1018 if ((nselected) || (dselected)) {
1019 Dialog* diag = this->pageSelector->getMoveNodesDialog();
1020 if ((diag) && (diag->isManaged())) {
1021 if (this->pageSelector->getSize() > 1)
1022 mscmd_activate = this->areSelectedNodesPagifiable(FALSE);
1023 else
1024 mscmd_activate = FALSE;
1025 } else {
1026 mscmd_activate = TRUE;
1027 }
1028 }
1029 if (mscmd_activate)
1030 this->moveSelectedCmd->activate();
1031 else
1032 this->moveSelectedCmd->deactivate();
1033
1034 //
1035 // Handle commands that depend on whether there are nodes selected
1036 //
1037 if (nselected == 0) {
1038 this->valuesCmd->deactivate();
1039 this->addInputTabCmd->deactivate();
1040 this->removeInputTabCmd->deactivate();
1041 this->addOutputTabCmd->deactivate();
1042 this->removeOutputTabCmd->deactivate();
1043 this->hideAllTabsCmd->deactivate();
1044 this->revealAllTabsCmd->deactivate();
1045 this->autoChopSelectedCmd->deactivate();
1046 this->autoFuseSelectedCmd->deactivate();
1047 if (dselected) {
1048 this->deleteNodeCmd->activate();
1049 this->cutNodeCmd->activate();
1050 this->copyNodeCmd->activate();
1051 this->pagifySelectedCmd->activate();
1052 } else {
1053 this->cutNodeCmd->deactivate();
1054 this->copyNodeCmd->deactivate();
1055 this->deleteNodeCmd->deactivate();
1056 this->pagifySelectedCmd->deactivate();
1057 }
1058 this->selectDownwardNodeCmd->deactivate();
1059 this->selectUpwardNodeCmd->deactivate();
1060 this->deselectAllNodeCmd->deactivate();
1061 this->selectConnectedNodeCmd->deactivate();
1062 #ifndef FORGET_GETSET
1063 if ((EditorWindow::GetSetDialog) &&
1064 (EditorWindow::GetSetDialog->isManaged()) &&
1065 (this == EditorWindow::GetSetDialog->getActiveEditor())) {
1066 this->SelectedToGlobalCmd->deactivate();
1067 this->SelectedToLocalCmd->deactivate();
1068 }
1069 this->toLocalCmd->deactivate();
1070 this->toGlobalCmd->deactivate();
1071 #endif
1072 this->selectUnconnectedNodeCmd->deactivate();
1073 this->selectUnselectedNodeCmd->deactivate(); // Same as selectAll
1074 this->macroifyCmd->deactivate();
1075 this->openColormapCmd->deactivate();
1076 this->openMacroCmd->deactivate();
1077 this->openImageCmd->deactivate();
1078 this->openControlPanelCmd->deactivate();
1079 this->editOutputCacheabilityCascade->deactivate();
1080 } else {
1081 //
1082 // Commands that can only work selected nodes, but depend on the Node.
1083 //
1084 boolean add_input = FALSE, remove_input = FALSE;
1085 boolean add_output = FALSE, remove_output = FALSE;
1086 boolean hide_all = FALSE, reveal_all = FALSE;
1087 boolean cacheable = FALSE;
1088 #ifndef FORGET_GETSET
1089 boolean only_gets_n_sets = TRUE;
1090 boolean convertible = TRUE;
1091 #endif
1092 Node *n;
1093 ListIterator iterator;
1094 FOR_EACH_NETWORK_NODE(this->network, n, iterator) {
1095 if ((n->getStandIn()) && (n->getStandIn()->isSelected()))
1096 {
1097 #ifndef FORGET_GETSET
1098 const char *cp = n->getNameString();
1099 if (!n->isA(ClassGlobalLocalNode))
1100 convertible = only_gets_n_sets = FALSE;
1101 else if ((!EqualString(cp, "Get")) && (!EqualString(cp, "Set")))
1102 only_gets_n_sets = FALSE;
1103 #endif
1104
1105 if (!add_input && n->isInputRepeatable())
1106 add_input = TRUE;
1107 if (!remove_input && n->hasRemoveableInput())
1108 remove_input = TRUE;
1109 if (!add_output && n->isOutputRepeatable())
1110 add_output = TRUE;
1111 if (!remove_output && n->hasRemoveableOutput())
1112 remove_output = TRUE;
1113 if (!hide_all &&
1114 (n->hasHideableInput() || n->hasHideableOutput()))
1115 hide_all = TRUE;
1116 if (!reveal_all &&
1117 (n->hasExposableInput() || n->hasExposableOutput()))
1118 reveal_all = TRUE;
1119 int count = n->getOutputCount();
1120 for (int i=1 ; !cacheable && i<=count ; i++)
1121 cacheable = n->isOutputCacheabilityWriteable(i);
1122 }
1123 }
1124 (add_input ? this->addInputTabCmd->activate() :
1125 this->addInputTabCmd->deactivate());
1126 (remove_input ? this->removeInputTabCmd->activate() :
1127 this->removeInputTabCmd->deactivate());
1128 (add_output ? this->addOutputTabCmd->activate() :
1129 this->addOutputTabCmd->deactivate());
1130 (remove_output? this->removeOutputTabCmd->activate() :
1131 this->removeOutputTabCmd->deactivate());
1132 (reveal_all ? this->revealAllTabsCmd->activate() :
1133 this->revealAllTabsCmd->deactivate());
1134 (hide_all ? this->hideAllTabsCmd->activate() :
1135 this->hideAllTabsCmd->deactivate());
1136 (cacheable ? this->editOutputCacheabilityCascade->activate() :
1137 this->editOutputCacheabilityCascade->deactivate());
1138 //
1139 // Commands that can only work if there are unselected nodes
1140 //
1141 if (nodes > nselected) {
1142 this->selectAllNodeCmd->activate();
1143 this->selectConnectedNodeCmd->activate();
1144 this->selectUnconnectedNodeCmd->activate();
1145 this->selectUnselectedNodeCmd->activate();
1146 this->selectDownwardNodeCmd->activate();
1147 this->selectUpwardNodeCmd->activate();
1148 } else { // There are no unselected nodes
1149 this->selectAllNodeCmd->deactivate();
1150 this->selectConnectedNodeCmd->deactivate();
1151 this->selectUnconnectedNodeCmd->deactivate();
1152 this->selectUnselectedNodeCmd->deactivate();
1153 this->selectDownwardNodeCmd->deactivate();
1154 this->selectUpwardNodeCmd->deactivate();
1155 }
1156 //
1157 // And commands that depend on the class of node that is selected.
1158 //
1159 List *l = this->makeSelectedNodeList(NULL);
1160 boolean selected_macro = FALSE, selected_image = FALSE;
1161 boolean selected_colormap = FALSE;
1162 boolean selected_interactor = FALSE;
1163 if (l) {
1164 ListIterator iterator(*l);
1165 Node *n;
1166 while ( (n = (Node*)iterator.getNext()) ) {
1167 if (!selected_colormap && n->isA(ClassColormapNode))
1168 selected_colormap = TRUE;
1169 if (!selected_macro && n->isA(ClassMacroNode))
1170 selected_macro = TRUE;
1171 if (!selected_image && n->isA(ClassDisplayNode))
1172 selected_image = TRUE;
1173 if (!selected_interactor && n->isA(ClassInteractorNode))
1174 selected_interactor = TRUE;
1175 }
1176 delete l;
1177 }
1178 (selected_macro ? this->openMacroCmd->activate() :
1179 this->openMacroCmd->deactivate());
1180 (selected_image ? this->openImageCmd->activate() :
1181 this->openImageCmd->deactivate());
1182 (selected_colormap ? this->openColormapCmd->activate() :
1183 this->openColormapCmd->deactivate());
1184 (selected_interactor ? this->openControlPanelCmd->activate() :
1185 this->openControlPanelCmd->deactivate());
1186 //
1187 // And...commands that can only work if there are selected nodes
1188 //
1189 this->valuesCmd->activate();
1190 this->macroifyCmd->activate();
1191 this->deleteNodeCmd->activate();
1192 this->cutNodeCmd->activate();
1193 this->copyNodeCmd->activate();
1194 this->deselectAllNodeCmd->activate();
1195 this->pagifySelectedCmd->activate();
1196 this->autoChopSelectedCmd->activate();
1197 this->autoFuseSelectedCmd->activate();
1198
1199 //
1200 // Convert Get/Set node commands. Requires that 1 or more nodes selected and
1201 // every node selected is a Get or Set.
1202 //
1203 #ifndef FORGET_GETSET
1204 if ((only_gets_n_sets) && (EditorWindow::GetSetDialog) &&
1205 (this != ew) && (EditorWindow::GetSetDialog->isManaged())) {
1206 EditorWindow::GetSetDialog->setActiveEditor(this);
1207 ew = EditorWindow::GetSetDialog->getActiveEditor();
1208 }
1209 if (convertible) {
1210 this->toLocalCmd->activate();
1211 this->toGlobalCmd->activate();
1212 } else {
1213 this->toLocalCmd->deactivate();
1214 this->toGlobalCmd->deactivate();
1215 }
1216 if ((EditorWindow::GetSetDialog) &&
1217 (EditorWindow::GetSetDialog->isManaged()) && (this == ew)) {
1218 if (only_gets_n_sets) {
1219 if (!ew) EditorWindow::GetSetDialog->setActiveEditor(this);
1220 this->SelectedToGlobalCmd->activate();
1221 this->SelectedToLocalCmd->activate();
1222 } else {
1223 this->SelectedToGlobalCmd->deactivate();
1224 this->SelectedToLocalCmd->deactivate();
1225 }
1226 }
1227 #endif
1228 }
1229
1230 //
1231 // If there is at least 1 image node
1232 //
1233 if (this->javifyNetCmd) {
1234 boolean activate = FALSE;
1235 List* bns = this->network->makeClassifiedNodeList(ClassImageNode);
1236 if ((bns) && (bns->getSize() > 0)) {
1237 activate = TRUE;
1238 }
1239 if (bns) delete bns;
1240 if (activate) {
1241 this->javifyNetCmd->activate();
1242 this->unjavifyNetCmd->activate();
1243 } else {
1244 this->javifyNetCmd->deactivate();
1245 this->unjavifyNetCmd->deactivate();
1246 }
1247 }
1248
1249 this->editTabsCascade->setActivationFromChildren();
1250 this->editSelectCascade->setActivationFromChildren();
1251 }
1252
1253 //
1254 // Do any work that is required when a Node's status changes (generally
1255 // called by a StandIn). Mostly what needs to be done is handle command
1256 // activation and deactivation.
1257 //
handleNodeStatusChange(Node * n,NodeStatusChange status)1258 void EditorWindow::handleNodeStatusChange(Node *n, NodeStatusChange status)
1259 {
1260
1261 switch (status) {
1262 case Node::NodeSelected:
1263 case Node::NodeDeselected:
1264 // FIXME: should we do this more quickly?
1265 this->deferrableCommandActivation->requestAction(NULL);
1266 if (n->isA(ClassTransmitterNode))
1267 this->lastSelectedTransmitter = (TransmitterNode*)n;
1268
1269 break;
1270 default:
1271 ASSERT(0);
1272 }
1273
1274 }
createWorkArea(Widget parent)1275 Widget EditorWindow::createWorkArea(Widget parent)
1276 {
1277 Widget form;
1278 Widget hBar;
1279 Widget vBar;
1280 Dimension height;
1281 Dimension width;
1282 Dimension thickness;
1283
1284 ASSERT(parent);
1285
1286 Widget outer_form = XtVaCreateManagedWidget ("workAreaFrame", xmFormWidgetClass,
1287 parent,
1288 XmNshadowType, XmSHADOW_OUT,
1289 XmNshadowThickness, 1,
1290 NULL);
1291
1292 form = XtVaCreateManagedWidget ("workArea", xmFormWidgetClass, outer_form,
1293 XmNtopAttachment, XmATTACH_FORM,
1294 XmNleftAttachment, XmATTACH_FORM,
1295 XmNrightAttachment, XmATTACH_FORM,
1296 XmNbottomAttachment, XmATTACH_FORM,
1297 XmNtopOffset, 6,
1298 XmNleftOffset, 6,
1299 XmNrightOffset, 6,
1300 XmNbottomOffset, 6,
1301 XmNshadowThickness, 0,
1302 NULL);
1303
1304
1305 //
1306 // Create the category/tool lists as a child of the above form.
1307 //
1308
1309 this->toolSelector = new EditorToolSelector("toolSelector", this);
1310 if (!this->toolSelector->initialize(form,theNodeDefinitionDictionary))
1311 ASSERT(0);
1312
1313 XtVaSetValues (this->toolSelector->getRootWidget(),
1314 XmNtopAttachment, XmATTACH_FORM,
1315 XmNleftAttachment, XmATTACH_FORM,
1316 XmNbottomAttachment, XmATTACH_FORM,
1317 XmNtopOffset, 0,
1318 XmNleftOffset, 0,
1319 XmNbottomOffset, 0,
1320 NULL);
1321
1322 #if WORKSPACE_PAGES
1323 this->pageSelector = new PageSelector (this, form, this->network);
1324 XtVaSetValues (this->pageSelector->getRootWidget(),
1325 XmNtopAttachment, XmATTACH_FORM,
1326 XmNleftAttachment, XmATTACH_WIDGET,
1327 XmNleftWidget, this->toolSelector->getRootWidget(),
1328 XmNleftOffset, 5,
1329 XmNrightAttachment, XmATTACH_FORM,
1330 XmNrightOffset, 20,
1331 NULL);
1332 #endif
1333
1334 //
1335 // Create the scrolled window.
1336 //
1337 this->scrolledWindow =
1338 XtVaCreateManagedWidget
1339 ("scrolledWindow",
1340 xmScrolledWindowWidgetClass,
1341 form,
1342 #if WORKSPACE_PAGES
1343 XmNtopAttachment, XmATTACH_WIDGET,
1344 XmNtopWidget, this->pageSelector->getRootWidget(),
1345 XmNtopOffset, -1,
1346 #else
1347 XmNtopAttachment, XmATTACH_FORM,
1348 #endif
1349 XmNleftAttachment, XmATTACH_WIDGET,
1350 XmNleftWidget, this->toolSelector->getRootWidget(),
1351 XmNleftOffset, 5,
1352 XmNrightAttachment, XmATTACH_FORM,
1353 XmNbottomAttachment, XmATTACH_FORM,
1354 XmNscrollingPolicy, XmAUTOMATIC,
1355 XmNvisualPolicy, XmVARIABLE,
1356 XmNscrollBarDisplayPolicy, XmAS_NEEDED,
1357 NULL);
1358 //
1359 // Create the workspace object.
1360 //
1361
1362 this->workSpace = new VPERoot("vpeCanvas", this->scrolledWindow,
1363 this->network->getWorkSpaceInfo(),
1364 this, this->pageSelector);
1365 this->workSpace->initializeRootWidget();
1366 this->workSpace->manage();
1367 this->pageSelector->setRootPage((VPERoot*)this->workSpace);
1368
1369 XtVaSetValues(this->scrolledWindow, XmNworkWindow,
1370 this->workSpace->getRootWidget(), NULL);
1371
1372 //
1373 // Adjust the horizontal/vertical scrollbars to get rid of
1374 // highlighting feature.
1375 //
1376 XtVaGetValues(this->scrolledWindow,
1377 XmNhorizontalScrollBar, &hBar,
1378 XmNverticalScrollBar, &vBar,
1379 NULL);
1380
1381 XtVaGetValues(hBar,
1382 XmNhighlightThickness, &thickness,
1383 XmNheight, &height,
1384 NULL);
1385 height -= thickness * 2;
1386 XtVaSetValues(hBar,
1387 XmNhighlightThickness, 0,
1388 XmNheight, height,
1389 NULL);
1390
1391 XtVaGetValues(vBar,
1392 XmNhighlightThickness, &thickness,
1393 XmNwidth, &width,
1394 NULL);
1395 width -= thickness * 2;
1396 XtVaSetValues(vBar,
1397 XmNhighlightThickness, 0,
1398 XmNwidth, width,
1399 NULL);
1400
1401 #if ((XmVERSION==2)&&(XmREVISION>=2))
1402 //
1403 // Pg {Up,Down} is crashing the vpe. If this bug goes away
1404 // then remove this code. Finding a bug fix for Motif isn't good
1405 // enough since we build with shared libraries. Another way
1406 // to fix this might have been to make a translation table
1407 // entry. I did try that but when I invoked the widget's
1408 // action routine, I got the same crash.
1409 //
1410 // Event handling in libXt is more complex than I what I can write
1411 // code for at this level. The 0 passed to this constructor is
1412 // supposed to be a window id. 0 means wildcard i.e. we match any
1413 // event. In KeyPress() we'll try to figure out if the widget
1414 // that belongs to this event is in the hierarchy of this window.
1415 //
1416 if (!this->pgKeyHandler) {
1417 this->pgKeyHandler = new XHandler(KeyPress, 0, KeyHandler, (void*)this);
1418 }
1419 #endif
1420 //
1421 // Return the topmost widget of the work area.
1422 //
1423 return outer_form;
1424 }
1425
1426
createFileMenu(Widget parent)1427 void EditorWindow::createFileMenu(Widget parent)
1428 {
1429 ASSERT(parent);
1430
1431 Widget pulldown;
1432 Command *cmd;
1433
1434 //
1435 // Create "File" menu and options.
1436 //
1437 pulldown =
1438 this->fileMenuPulldown =
1439 XmCreatePulldownMenu(parent, "fileMenuPulldown", NUL(ArgList), 0);
1440 this->fileMenu =
1441 XtVaCreateManagedWidget
1442 ("fileMenu",
1443 xmCascadeButtonWidgetClass,
1444 parent,
1445 XmNsubMenuId, pulldown,
1446 NULL);
1447
1448 this->newOption =
1449 new ButtonInterface(pulldown,
1450 "vpeNewOption",
1451 this->network->getNewCommand());
1452
1453 this->openOption =
1454 new ButtonInterface(pulldown,
1455 "vpeOpenOption", theDXApplication->openFileCmd);
1456
1457 this->createFileHistoryMenu(pulldown);
1458
1459 if ( (cmd = this->network->getSaveCommand()) ) {
1460 if(this->network->isMacro() == FALSE)
1461 this->saveOption = new ButtonInterface(pulldown, "vpeSaveOption", cmd);
1462 else
1463 this->saveOption = new ButtonInterface(pulldown, "vpeSaveMacroOption", cmd);
1464 }
1465
1466 if ( (cmd = this->network->getSaveAsCommand()) ) {
1467 if(this->network->isMacro() == FALSE)
1468 this->saveAsOption = new ButtonInterface(pulldown,
1469 "vpeSaveAsOption", cmd);
1470 else
1471 this->saveAsOption = new ButtonInterface(pulldown,
1472 "vpeSaveMacroAsOption", cmd);
1473 }
1474
1475
1476 Command *openCfgCmd = this->network->getOpenCfgCommand();
1477 Command *saveCfgCmd = this->network->getSaveCfgCommand();
1478 if (openCfgCmd && saveCfgCmd) {
1479 this->settingsCascade = new CascadeMenu("vpeSettingsCascade",pulldown);
1480 Widget menu_parent = this->settingsCascade->getMenuItemParent();
1481 this->saveCfgOption = new ButtonInterface(menu_parent,
1482 "vpeSaveCfgOption", saveCfgCmd);
1483 this->openCfgOption = new ButtonInterface(menu_parent,
1484 "vpeOpenCfgOption", openCfgCmd);
1485 } else if (openCfgCmd) {
1486 this->openCfgOption = new ButtonInterface(pulldown,
1487 "vpeOpenCfgOption", openCfgCmd);
1488 } else if (saveCfgCmd) {
1489 this->saveCfgOption = new ButtonInterface(pulldown,
1490 "vpeSaveCfgOption", saveCfgCmd);
1491 }
1492
1493
1494 XtVaCreateManagedWidget
1495 ("optionSeparator", xmSeparatorWidgetClass, pulldown, NULL);
1496
1497 this->loadMacroOption =
1498 new ButtonInterface(pulldown,
1499 "vpeLoadMacroOption", theDXApplication->loadMacroCmd);
1500 this->loadMDFOption =
1501 new ButtonInterface(pulldown,
1502 "vpeLoadMDFOption", theDXApplication->loadMDFCmd);
1503
1504 XtVaCreateManagedWidget
1505 ("optionSeparator", xmSeparatorWidgetClass, pulldown, NULL);
1506
1507 this->printProgramOption = new ButtonInterface(pulldown,
1508 "vpePrintProgramOption",
1509 this->printProgramCmd);
1510 if (this->saveAsCCodeCmd)
1511 this->saveAsCCodeOption = new ButtonInterface(pulldown,
1512 "vpeSaveAsCCodeOption",
1513 this->saveAsCCodeCmd);
1514 XtVaCreateManagedWidget
1515 ("optionSeparator", xmSeparatorWidgetClass, pulldown, NULL);
1516
1517 if (this->isAnchor() && theDXApplication->appAllowsExitOptions())
1518 this->quitOption =
1519 new ButtonInterface(pulldown,"quitOption",theDXApplication->exitCmd);
1520 else
1521 this->closeOption =
1522 new ButtonInterface(pulldown,"vpeCloseOption",this->closeCmd);
1523
1524 XtAddCallback(pulldown,
1525 XmNmapCallback,
1526 (XtCallbackProc)EditorWindow_FileMenuMapCB,
1527 (XtPointer)this);
1528 }
1529
1530
createEditMenu(Widget parent)1531 void EditorWindow::createEditMenu(Widget parent)
1532 {
1533 ASSERT(parent);
1534
1535 Widget pulldown;
1536 CascadeMenu *cascade_menu;
1537 Widget menu_parent;
1538 CommandInterface *ci;
1539
1540 //
1541 // Create "Edit" menu and options.
1542 //
1543 pulldown =
1544 this->editMenuPulldown =
1545 XmCreatePulldownMenu(parent, "editMenuPulldown", NUL(ArgList), 0);
1546 this->editMenu =
1547 XtVaCreateManagedWidget
1548 ("editMenu",
1549 xmCascadeButtonWidgetClass,
1550 parent,
1551 XmNsubMenuId, pulldown,
1552 NULL);
1553
1554 this->undoOption = new ButtonInterface (pulldown, "vpeUndoOption", this->undoCmd);
1555 XtVaCreateManagedWidget ("optionSeparator", xmSeparatorWidgetClass, pulldown, NULL);
1556
1557 //
1558 // Module level functions
1559 //
1560 this->valuesOption =
1561 new ButtonInterface(pulldown, "vpeValuesOption", this->valuesCmd);
1562
1563 this->findToolOption =
1564 new ButtonInterface(pulldown, "vpeFindToolOption", this->findToolCmd);
1565
1566
1567 //
1568 // Add/removing tabs
1569 //
1570 #if 0
1571 XtVaCreateManagedWidget("optionSeparator", xmSeparatorWidgetClass,
1572 pulldown, NULL);
1573 #endif
1574 cascade_menu = this->editTabsCascade =
1575 new CascadeMenu("vpeEditTabsCascade",pulldown);
1576 menu_parent = cascade_menu->getMenuItemParent();
1577
1578
1579 this->addInputTabOption = new ButtonInterface(menu_parent, "vpeAddInputTabOption",
1580 this->addInputTabCmd);
1581 cascade_menu->appendComponent(this->addInputTabOption);
1582
1583 this->removeInputTabOption = new ButtonInterface(menu_parent, "vpeRemoveInputTabOption",
1584 this->removeInputTabCmd);
1585 cascade_menu->appendComponent(this->removeInputTabOption);
1586 ci = new ButtonInterface(menu_parent, "vpeAddOutputTabOption",
1587 this->addOutputTabCmd);
1588 cascade_menu->appendComponent(ci);
1589
1590 ci = new ButtonInterface(menu_parent, "vpeRemoveOutputTabOption",
1591 this->removeOutputTabCmd);
1592 cascade_menu->appendComponent(ci);
1593
1594 ci = new ButtonInterface(menu_parent, "vpeRevealAllTabsOption",
1595 this->revealAllTabsCmd);
1596 cascade_menu->appendComponent(ci);
1597
1598 ci = new ButtonInterface(menu_parent, "vpeHideAllTabsOption",
1599 this->hideAllTabsCmd);
1600 cascade_menu->appendComponent(ci);
1601
1602 #ifndef FORGET_GETSET
1603 //
1604 // GetSet Conversion operation
1605 //
1606 cascade_menu = this->programVerifyCascade =
1607 new CascadeMenu("programVerifyCascade",pulldown);
1608 menu_parent = cascade_menu->getMenuItemParent();
1609
1610 ci = new ButtonInterface (menu_parent, "getSetConversion", this->postGetSetCmd);
1611 cascade_menu->appendComponent(ci);
1612
1613 ci = new ButtonInterface (menu_parent, "setToLocal", this->toLocalCmd);
1614 cascade_menu->appendComponent(ci);
1615
1616 ci = new ButtonInterface (menu_parent, "setToGlobal", this->toGlobalCmd);
1617 cascade_menu->appendComponent(ci);
1618 #endif
1619
1620 //
1621 // Module selection methods
1622 //
1623 #if 0
1624 XtVaCreateManagedWidget("optionSeparator", xmSeparatorWidgetClass,
1625 pulldown, NULL);
1626 #endif
1627
1628 this->editSelectCascade =
1629 cascade_menu = new CascadeMenu("vpeEditSelectCascade",pulldown);
1630 menu_parent = cascade_menu->getMenuItemParent();
1631
1632 ci = new ButtonInterface(menu_parent, "vpeSelectAllOption",
1633 this->selectAllNodeCmd);
1634 cascade_menu->appendComponent(ci);
1635
1636 ci = new ButtonInterface(menu_parent, "vpeSelectConnectedOption",
1637 this->selectConnectedNodeCmd);
1638 cascade_menu->appendComponent(ci);
1639
1640 ci = new ButtonInterface(menu_parent, "vpeSelectUnconnectedOption",
1641 this->selectUnconnectedNodeCmd);
1642 cascade_menu->appendComponent(ci);
1643
1644 ci = new ButtonInterface(menu_parent, "vpeSelectUpwardOption",
1645 this->selectUpwardNodeCmd);
1646 cascade_menu->appendComponent(ci);
1647
1648 ci = new ButtonInterface(menu_parent, "vpeSelectDownwardOption",
1649 this->selectDownwardNodeCmd);
1650 cascade_menu->appendComponent(ci);
1651
1652 ci = new ButtonInterface(menu_parent, "vpeDeselectAllOption",
1653 this->deselectAllNodeCmd);
1654 cascade_menu->appendComponent(ci);
1655
1656 ci = new ButtonInterface(menu_parent, "vpeSelectUnselectedOption",
1657 this->selectUnselectedNodeCmd);
1658 cascade_menu->appendComponent(ci);
1659
1660 ci = new ButtonInterface (menu_parent, "vpeShowExecutedOption",
1661 this->showExecutedCmd);
1662 cascade_menu->appendComponent(ci);
1663
1664 //
1665 // Output Cacheability (two cascade menus)
1666 //
1667 this->outputCacheabilityCascade =
1668 cascade_menu = new CascadeMenu("vpeOutputCacheabilityCascade",pulldown);
1669 menu_parent = cascade_menu->getMenuItemParent();
1670
1671 ci = new ButtonInterface(menu_parent, "vpeOptimizeCacheability",
1672 this->optimizeCacheabilityCmd);
1673 cascade_menu->appendComponent(ci);
1674
1675 // Set
1676 this->editOutputCacheabilityCascade =
1677 cascade_menu = new CascadeMenu("vpeEditOutputCacheabilityCascade",
1678 menu_parent);
1679 menu_parent = cascade_menu->getMenuItemParent();
1680
1681 ci = new ButtonInterface(menu_parent, "vpeCacheAllOutputsOption",
1682 this->cacheAllOutputsCmd);
1683 cascade_menu->appendComponent(ci);
1684
1685 ci = new ButtonInterface(menu_parent, "vpeCacheLastOutputsOption",
1686 this->cacheLastOutputsCmd);
1687 cascade_menu->appendComponent(ci);
1688
1689 ci = new ButtonInterface(menu_parent, "vpeCacheNoOutputsOption",
1690 this->cacheNoOutputsCmd);
1691 cascade_menu->appendComponent(ci);
1692 // Show
1693 menu_parent = this->outputCacheabilityCascade->getMenuItemParent();
1694 cascade_menu = new CascadeMenu("vpeShowOutputCacheabilityCascade",
1695 menu_parent);
1696 this->outputCacheabilityCascade->appendComponent(cascade_menu);
1697 menu_parent = cascade_menu->getMenuItemParent();
1698
1699 ci = new ButtonInterface(menu_parent, "vpeShowCacheAllOutputsOption",
1700 this->showCacheAllOutputsCmd);
1701 cascade_menu->appendComponent(ci);
1702
1703 ci = new ButtonInterface(menu_parent, "vpeShowCacheLastOutputsOption",
1704 this->showCacheLastOutputsCmd);
1705 cascade_menu->appendComponent(ci);
1706
1707 ci = new ButtonInterface(menu_parent, "vpeShowCacheNoOutputsOption",
1708 this->showCacheNoOutputsCmd);
1709 cascade_menu->appendComponent(ci);
1710
1711 //
1712 // Delete, Cut, Copy, Paste
1713 //
1714 XtVaCreateManagedWidget("optionSeparator", xmSeparatorWidgetClass,
1715 pulldown, NULL);
1716 this->deleteOption =
1717 new ButtonInterface(pulldown, "vpeDeleteOption", this->deleteNodeCmd);
1718
1719 if ((theDXApplication->appAllowsSavingNetFile()) &&
1720 (theDXApplication->appAllowsSavingCfgFile()) &&
1721 (theDXApplication->appAllowsEditorAccess())) {
1722 this->copyOption =
1723 new ButtonInterface(pulldown, "vpeCopyOption", this->copyNodeCmd);
1724
1725 this->cutOption =
1726 new ButtonInterface(pulldown, "vpeCutOption", this->cutNodeCmd);
1727
1728 this->pasteOption =
1729 new ButtonInterface(pulldown, "vpePasteOption", this->pasteNodeCmd);
1730 }
1731
1732 //
1733 // Annotation
1734 //
1735 XtVaCreateManagedWidget("optionSeparator", xmSeparatorWidgetClass,
1736 pulldown, NULL);
1737
1738 this->addAnnotationOption = new ButtonInterface(pulldown, "vpeAddDecorator",
1739 this->addAnnotationCmd);
1740
1741 //
1742 // Miscellaneous
1743 //
1744 this->insertNetworkOption =
1745 new ButtonInterface(pulldown, "vpeInsertNetOption",
1746 this->insertNetCmd);
1747
1748 this->createMacroOption =
1749 new ButtonInterface(pulldown, "vpeCreateMacroOption",
1750 this->macroifyCmd);
1751
1752 #if WORKSPACE_PAGES
1753 this->pageCascade = cascade_menu = new CascadeMenu("vpePageCascade", pulldown);
1754 menu_parent = cascade_menu->getMenuItemParent();
1755
1756 ci = new ButtonInterface(menu_parent, "vpeCreatePageOption", this->pagifyCmd);
1757 cascade_menu->appendComponent(ci);
1758
1759 ci=new ButtonInterface(menu_parent, "vpeSelectedPageOption", this->pagifySelectedCmd);
1760 cascade_menu->appendComponent(ci);
1761
1762 ci = new ButtonInterface(menu_parent, "vpeDeletePageOption", this->deletePageCmd);
1763 cascade_menu->appendComponent(ci);
1764
1765 XtVaCreateManagedWidget("optionSeparator", xmSeparatorWidgetClass, menu_parent, NULL);
1766
1767 ci=new ButtonInterface(menu_parent, "vpeChopPageOption", this->autoChopSelectedCmd);
1768 cascade_menu->appendComponent(ci);
1769
1770 ci=new ButtonInterface(menu_parent, "vpeFusePageOption", this->autoFuseSelectedCmd);
1771 cascade_menu->appendComponent(ci);
1772
1773 XtVaCreateManagedWidget("optionSeparator", xmSeparatorWidgetClass, menu_parent, NULL);
1774
1775 ci = new ButtonInterface(menu_parent,"vpeConfigurePageOption",this->configurePageCmd);
1776 cascade_menu->appendComponent(ci);
1777
1778 ci = new ButtonInterface(menu_parent, "vpeMoveToPageOption", this->moveSelectedCmd);
1779 cascade_menu->appendComponent(ci);
1780 #endif
1781
1782 if (this->javifyNetCmd) {
1783 this->javaCascade = cascade_menu = new CascadeMenu("vpeJavaCascade", pulldown);
1784 menu_parent = cascade_menu->getMenuItemParent();
1785
1786 ci = new ButtonInterface(menu_parent,
1787 "vpeJavifyNetOption", this->javifyNetCmd);
1788 cascade_menu->appendComponent(ci);
1789
1790 ci = new ButtonInterface(menu_parent,
1791 "vpeUnjavifyNetOption", this->unjavifyNetCmd);
1792 cascade_menu->appendComponent(ci);
1793
1794 Command* cmd = NUL(Command*);
1795 cmd = this->network->getSaveWebPageCommand();
1796 if (cmd) {
1797 XtVaCreateManagedWidget("optionSeparator",
1798 xmSeparatorWidgetClass, menu_parent, NULL);
1799 ci = new ButtonInterface(menu_parent, "vpeSaveWebPageOption", cmd);
1800 cascade_menu->appendComponent(ci);
1801 }
1802
1803 cmd = this->network->getSaveAppletCommand();
1804 if (cmd) {
1805 ci = new ButtonInterface(menu_parent, "vpeSaveAppletOption", cmd);
1806 cascade_menu->appendComponent(ci);
1807 }
1808
1809 cmd = this->network->getSaveBeanCommand();
1810 if (cmd) {
1811 ci = new ButtonInterface(menu_parent, "vpeSaveBeanOption", cmd);
1812 cascade_menu->appendComponent(ci);
1813 }
1814
1815 }
1816
1817 this->macroNameOption =
1818 new ButtonInterface(pulldown, "vpeMacroNameOption",
1819 this->network->getSetNameCommand());
1820
1821 this->reflowGraphOption =
1822 new ButtonInterface(pulldown, "vpeReflowGraphOption",
1823 this->reflowGraphCmd);
1824
1825 this->createProcessGroupOption =
1826 new ButtonInterface(pulldown, "vpeCreateProcessGroupOption",
1827 this->createProcessGroupCmd);
1828
1829 this->commentOption =
1830 new ButtonInterface(pulldown, "vpeCommentOption", this->editCommentCmd);
1831
1832 XtAddCallback(pulldown,
1833 XmNmapCallback,
1834 (XtCallbackProc)EditorWindow_EditMenuMapCB,
1835 (XtPointer)this);
1836 }
1837
1838
createWindowsMenu(Widget parent)1839 void EditorWindow::createWindowsMenu(Widget parent)
1840 {
1841 ASSERT(parent);
1842
1843 Widget pulldown;
1844
1845 //
1846 // Create "Windows" menu and options.
1847 //
1848 pulldown =
1849 this->windowsMenuPulldown =
1850 XmCreatePulldownMenu
1851 (parent, "windowsMenuPulldown", NUL(ArgList), 0);
1852 this->windowsMenu =
1853 XtVaCreateManagedWidget
1854 ("windowsMenu",
1855 xmCascadeButtonWidgetClass,
1856 parent,
1857 XmNsubMenuId, pulldown,
1858 NULL);
1859
1860 this->newControlPanelOption =
1861 new ButtonInterface
1862 (pulldown, "vpeNewControlPanelOption", this->newControlPanelCmd);
1863
1864 this->openControlPanelOption =
1865 new ButtonInterface(pulldown, "vpeOpenControlPanelOption",
1866 this->openControlPanelCmd);
1867
1868 this->openAllControlPanelsOption =
1869 new ButtonInterface
1870 (pulldown,
1871 "vpeOpenAllControlPanelsOption",
1872 this->network->getOpenAllPanelsCommand());
1873
1874 this->openControlPanelByNameMenu =
1875 new CascadeMenu("vpePanelCascade",pulldown);
1876
1877 XtAddCallback(pulldown,
1878 XmNmapCallback,
1879 (XtCallbackProc)EditorWindow_WindowMenuMapCB,
1880 (XtPointer)this);
1881
1882 #ifdef PANEL_GROUP_SEPARATED
1883 this->panelGroupPulldown =
1884 XmCreatePulldownMenu
1885 (pulldown, "panelGroupPulldown", NUL(ArgList), 0);
1886
1887 this->panelGroupCascade =
1888 cascade = XtVaCreateManagedWidget
1889 ("vpePanelGroupCascade",
1890 xmCascadeButtonWidgetClass,
1891 pulldown,
1892 XmNsubMenuId, this->panelGroupPulldown,
1893 XmNsensitive, TRUE,
1894 NULL);
1895 #endif
1896
1897 XtVaCreateManagedWidget("optionSeparator",
1898 xmSeparatorWidgetClass, pulldown, NULL);
1899
1900 this->openMacroOption =
1901 new ButtonInterface(pulldown, "vpeOpenMacroOption",
1902 this->openMacroCmd);
1903
1904 this->openImageOption =
1905 new ButtonInterface(pulldown, "vpeOpenImageOption",
1906 this->openImageCmd);
1907
1908 this->openColormapEditorOption =
1909 new ButtonInterface
1910 (pulldown, "vpeOpenColormapEditorOption", this->openColormapCmd);
1911
1912 this->messageWindowOption =
1913 new ButtonInterface
1914 (pulldown, "vpeMessageWindowOption",
1915 theDXApplication->messageWindowCmd);
1916
1917
1918 }
1919
1920
createOptionsMenu(Widget parent)1921 void EditorWindow::createOptionsMenu(Widget parent)
1922 {
1923 ASSERT(parent);
1924
1925 Widget pulldown;
1926
1927 //
1928 // Create "Options" menu and options.
1929 //
1930 pulldown =
1931 this->optionsMenuPulldown =
1932 XmCreatePulldownMenu
1933 (parent, "optionsMenuPulldown", NUL(ArgList), 0);
1934 this->optionsMenu =
1935 XtVaCreateManagedWidget
1936 ("optionsMenu",
1937 xmCascadeButtonWidgetClass,
1938 parent,
1939 XmNsubMenuId, pulldown,
1940 NULL);
1941
1942 this->toolPalettesOption =
1943 new ToggleButtonInterface
1944 (pulldown,
1945 "vpeToolPalettesOption",
1946 this->toolPanelCmd,
1947 this->panelVisible);
1948
1949 this->hitDetectionOption =
1950 new ToggleButtonInterface
1951 (pulldown,
1952 "vpeHitDetectionOption",
1953 this->hitDetectionCmd,
1954 this->hit_detection);
1955
1956 this->panelAccessOption =
1957 new ButtonInterface(pulldown, "vpePanelAccessOption", this->setPanelAccessCmd);
1958
1959 this->panelGroupOption =
1960 new ButtonInterface(pulldown, "vpePanelGroupOption", this->setPanelGroupCmd);
1961
1962 this->gridOption =
1963 new ButtonInterface(pulldown, "vpeGridOption", this->gridCmd);
1964
1965 XtAddCallback(pulldown, XmNmapCallback, (XtCallbackProc)
1966 EditorWindow_OptionsMenuMapCB, (XtPointer)this);
1967 }
1968
createHelpMenu(Widget parent)1969 void EditorWindow::createHelpMenu(Widget parent)
1970 {
1971 ASSERT(parent);
1972
1973 this->DXWindow::createHelpMenu(parent);
1974
1975 XtVaCreateManagedWidget("separator", xmSeparatorWidgetClass,
1976 this->helpMenuPulldown,
1977 NULL);
1978
1979 this->onVisualProgramOption =
1980 new ButtonInterface(this->helpMenuPulldown, "vpeOnVisualProgramOption",
1981 this->network->getHelpOnNetworkCommand());
1982 }
1983
1984
createMenus(Widget parent)1985 void EditorWindow::createMenus(Widget parent)
1986 {
1987 ASSERT(parent);
1988
1989 //
1990 // Create the menus.
1991 //
1992 this->createFileMenu(parent);
1993 this->createEditMenu(parent);
1994 this->createExecuteMenu(parent);
1995 this->createWindowsMenu(parent);
1996 this->createConnectionMenu(parent);
1997 this->createOptionsMenu(parent);
1998 this->createHelpMenu(parent);
1999
2000 //
2001 // Right justify the help menu (if it exists).
2002 //
2003 if (this->helpMenu)
2004 {
2005 XtVaSetValues(parent, XmNmenuHelpWidget, this->helpMenu, NULL);
2006 }
2007 }
2008
2009
toggleToolPanel()2010 void EditorWindow::toggleToolPanel()
2011 {
2012 Widget toolpanel = this->toolSelector->getRootWidget();
2013
2014 this->panelVisible = NOT this->panelVisible;
2015 if (!this->panelVisible) {
2016 //
2017 // Unmanage the control panel.
2018 //
2019 XtUnmanageChild(toolpanel);
2020 XtVaSetValues (this->scrolledWindow,
2021 XmNleftAttachment, XmATTACH_FORM,
2022 XmNleftOffset, 0,
2023 NULL);
2024 #if WORKSPACE_PAGES
2025 XtVaSetValues (this->pageSelector->getRootWidget(),
2026 XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 0, NULL);
2027 #endif
2028 } else {
2029 //
2030 // Manage the control panel.
2031 //
2032 XtVaSetValues (this->scrolledWindow,
2033 XmNleftAttachment, XmATTACH_WIDGET,
2034 XmNleftWidget, toolpanel,
2035 XmNleftOffset, 5,
2036 NULL);
2037 XtManageChild(toolpanel);
2038 #if WORKSPACE_PAGES
2039 XtVaSetValues (this->pageSelector->getRootWidget(),
2040 XmNleftAttachment, XmATTACH_WIDGET, XmNleftOffset, 5,
2041 XmNleftWidget, toolpanel, NULL);
2042 #endif
2043 }
2044 }
2045
EditorWindow_EditMenuMapCB(Widget widget,XtPointer clientdata,XtPointer calldata)2046 extern "C" void EditorWindow_EditMenuMapCB(Widget widget,
2047 XtPointer clientdata,
2048 XtPointer calldata)
2049 {
2050
2051 //
2052 // We do this here, because the editor does not get notified
2053 // when a node has the number repeatable inputs reduced to zero
2054 // and so can't grey out the 'Remove input' option. This same argument
2055 // works for other add/remove repeatable input/output options.
2056 //
2057 EditorWindow *editor = (EditorWindow*)clientdata;
2058 editor->deferrableCommandActivation->requestAction(NULL);
2059
2060 //
2061 // {de}activate the paste option based on selection ownership.
2062 // setCommandActivation() isn't really the right place for these
2063 // because there is no event or notification received when some other
2064 // vpe establishes or loses selection ownership.
2065 //
2066 Display *d = XtDisplay(widget);
2067 Atom file_atom = XmInternAtom (d, NET_ATOM, True);
2068 if (file_atom) {
2069 Window win = XGetSelectionOwner (d, file_atom);
2070 if (win == None) editor->pasteNodeCmd->deactivate();
2071 else editor->pasteNodeCmd->activate();
2072 } else
2073 editor->pasteNodeCmd->deactivate();
2074 }
EditorWindow_FileMenuMapCB(Widget widget,XtPointer clientdata,XtPointer calldata)2075 extern "C" void EditorWindow_FileMenuMapCB(Widget widget,
2076 XtPointer clientdata,
2077 XtPointer calldata)
2078 {
2079 EditorWindow *editor = (EditorWindow*)clientdata;
2080
2081 if(editor->isAnchor() )
2082 {
2083 if (editor->quitOption) {
2084 if(editor->network->saveToFileRequired())
2085 ((ButtonInterface*)editor->quitOption)->setLabel("Quit...");
2086 else
2087 ((ButtonInterface*)editor->quitOption)->setLabel("Quit");
2088 }
2089 }
2090 else
2091 {
2092 editor->newOption->deactivate();
2093 editor->openOption->deactivate();
2094 editor->loadMDFOption->deactivate();
2095 editor->loadMacroOption->deactivate();
2096 }
2097
2098 }
2099
EditorWindow_WindowMenuMapCB(Widget widget,XtPointer clientdata,XtPointer calldata)2100 extern "C" void EditorWindow_WindowMenuMapCB(Widget widget,
2101 XtPointer clientdata,
2102 XtPointer calldata)
2103 {
2104 EditorWindow *editor = (EditorWindow*)clientdata;
2105
2106 Network *network = editor->network;
2107 CascadeMenu *menu = editor->openControlPanelByNameMenu;
2108 PanelAccessManager *panelMgr = network->getPanelAccessManager();
2109 network->fillPanelCascade(menu, panelMgr);
2110 }
2111
2112 extern "C"
EditorWindow_OptionsMenuMapCB(Widget widget,XtPointer clientdata,XtPointer)2113 void EditorWindow_OptionsMenuMapCB(Widget widget, XtPointer clientdata, XtPointer )
2114 {
2115 EditorWindow *editor = (EditorWindow*)clientdata;
2116 EditorWorkSpace* ews = editor->workSpace;
2117 WorkSpaceInfo* info = ews->getInfo();
2118 ToggleButtonInterface* tbi = (ToggleButtonInterface*)
2119 editor->hitDetectionOption;
2120 editor->hit_detection = info->getPreventOverlap();
2121 tbi->setState(editor->hit_detection);
2122 }
2123
openSelectedINodes()2124 void EditorWindow::openSelectedINodes()
2125 {
2126 Node *node;
2127 List *snlist = this->makeSelectedNodeList();
2128
2129 if(NOT snlist)
2130 return;
2131
2132 ListIterator li(*snlist);
2133
2134 while( (node = (Node*)li.getNext()) )
2135 if(node->isA(ClassInteractorNode))
2136 ((InteractorNode*)node)->openControlPanels(this->getRootWidget());
2137
2138 delete snlist;
2139 }
2140
2141 #if WORKSPACE_PAGES
2142 EditorWorkSpace*
getPage(const char * pageName)2143 EditorWindow::getPage (const char *pageName)
2144 {
2145 EditorWorkSpace *page =
2146 (EditorWorkSpace*)this->pageSelector->findDefinition(pageName);
2147
2148 //
2149 // If the page hasn't been created yet, then find its info from the
2150 // page manager.
2151 //
2152 if (!page) {
2153 PageGroupManager *pmgr = (PageGroupManager*)
2154 this->network->getGroupManagers()->findDefinition(PAGE_GROUP);
2155 PageGroupRecord *prec = (PageGroupRecord*)pmgr->getGroup (pageName);
2156 ASSERT(prec);
2157 page = (EditorWorkSpace*)this->workSpace->addPage();
2158 ASSERT (this->pageSelector->addDefinition (pageName, page));
2159 }
2160
2161 return page;
2162 }
2163 #endif
2164
newNode(Node * n,EditorWorkSpace * where)2165 void EditorWindow::newNode(Node *n, EditorWorkSpace *where)
2166 {
2167 StandIn *si;
2168 List *arcs;
2169 Ark *a;
2170 int icnt, i, j;
2171 const char *cp;
2172
2173 si = n->getStandIn();
2174
2175 //
2176 // We don't want to always create a new StandIn, because when
2177 // undeleting a node, the standin already exists.
2178 //
2179 if (!si) {
2180 if (where) {
2181 n->newStandIn(where);
2182 #if WORKSPACE_PAGES
2183 GroupRecord* grec = this->getGroupOfWorkSpace(where);
2184 Symbol page_sym = theSymbolManager->getSymbol(PAGE_GROUP);
2185 if (grec) n->setGroupName(grec, page_sym);
2186 #endif
2187 }
2188 #if WORKSPACE_PAGES
2189 else if ( (cp = n->getGroupName(theSymbolManager->getSymbol(PAGE_GROUP))) ) {
2190 EditorWorkSpace *page = this->getPage(cp);
2191 ASSERT(page);
2192 //
2193 // If page is the current page, then make a standin.
2194 //
2195 int page_num = this->workSpace->getCurrentPage();
2196 EditorWorkSpace* ews = this->workSpace;
2197 if (page_num)
2198 ews = (EditorWorkSpace*)this->workSpace->getElement(page_num);
2199 if (ews == page)
2200 n->newStandIn(page);
2201 else
2202 page->setMembersInitialized(FALSE);
2203 } else {
2204 int page_num = this->workSpace->getCurrentPage();
2205 EditorWorkSpace* page = this->workSpace;
2206 if (page_num)
2207 page = (EditorWorkSpace*)this->workSpace->getElement(page_num);
2208 GroupRecord* grec = this->getGroupOfWorkSpace(page);
2209 Symbol page_sym = theSymbolManager->getSymbol(PAGE_GROUP);
2210 if (grec) n->setGroupName(grec, page_sym);
2211 n->newStandIn(page);
2212 }
2213 #else
2214 else
2215 n->newStandIn(this->workSpace);
2216 #endif
2217 si = n->getStandIn();
2218 if (si) {
2219 icnt = n->getInputCount();
2220 for (i=1 ; i<=icnt ; i++) {
2221 arcs = (List *)n->getInputArks(i);
2222 for (j = 1; (a = (Ark*) arcs->getElement(j)); j++)
2223 this->notifyArk(a);
2224 si->drawTab(i, FALSE);
2225 }
2226 }
2227 } else {
2228 si->manage();
2229 si->drawArks(n);
2230 }
2231
2232 if (this->workSpace->isManaged())
2233 this->deferrableCommandActivation->requestAction(NULL);
2234 }
2235
2236
newNetwork()2237 void EditorWindow::newNetwork()
2238 {
2239 Node *node;
2240 ListIterator iterator;
2241
2242 this->prepareForNewNetwork();
2243
2244 // This is in case this is the first program being displayed.
2245 if (this->workSpace->isManaged())
2246 this->workSpace->unmanage();
2247
2248 FOR_EACH_NETWORK_NODE(this->network, node, iterator) {
2249 this->newNode(node, NUL(EditorWorkSpace*));
2250 }
2251
2252 this->deferrableCommandActivation->requestAction(NULL);
2253
2254 this->workSpace->manage();
2255
2256 this->completeNewNetwork();
2257 }
2258
manage()2259 void EditorWindow::manage()
2260 {
2261 this->DXWindow::manage();
2262 if (this->initialNetwork)
2263 {
2264 this->newNetwork();
2265 this->initialNetwork = FALSE;
2266 }
2267 Decorator *dec;
2268 ListIterator it;
2269
2270
2271 FOR_EACH_NETWORK_DECORATOR(this->network,dec,it) {
2272 #if WORKSPACE_PAGES
2273 const char* cp;
2274 VPEAnnotator *vpea = (VPEAnnotator*)dec;
2275 if ( (cp = vpea->getGroupName(theSymbolManager->getSymbol(PAGE_GROUP))) ) {
2276 EditorWorkSpace *page = this->getPage(cp);
2277 ASSERT(page);
2278 } else
2279 #endif
2280 {
2281 int page_num = this->workSpace->getCurrentPage();
2282 EditorWorkSpace* page = this->workSpace;
2283 if (page_num)
2284 page = (EditorWorkSpace*)this->workSpace->getElement(page_num);
2285 if (!dec->isManaged())
2286 dec->manage (page);
2287 }
2288 }
2289 }
2290
2291 //
2292 // Return a pointer to the editor's notion of the 'current' ControlPanel.
2293 // The return panel may or may not be managed.
2294 //
getCurrentControlPanel(void)2295 ControlPanel *EditorWindow::getCurrentControlPanel(void)
2296 {
2297 if (!this->currentPanel)
2298 this->currentPanel = this->network->newControlPanel();
2299
2300 return this->currentPanel;
2301 }
2302
2303
2304 //
2305 // Implements the 'Values' command.
2306 //
showValues()2307 void EditorWindow::showValues()
2308 {
2309 this->openSelectedNodesCDB();
2310 }
2311 //
2312 // Implements the 'Add/Remove Input/Output Tab' commands.
2313 // If 'adding' is TRUE, we ADD either inputs or outputs, otherwise
2314 // REMOVE.
2315 // If 'input' is true, we operate on the input parameters, otherwise
2316 // the outputs.
2317 //
editSelectedNodeTabs(boolean adding,boolean input)2318 boolean EditorWindow::editSelectedNodeTabs(boolean adding, boolean input)
2319 {
2320 List *l = this->makeSelectedNodeList();
2321 if (l == NULL || l->getSize() == 0) {
2322 if (l) delete l;
2323 return TRUE;
2324 }
2325
2326 Node *node;
2327 boolean r = TRUE;
2328 ListIterator li(*l);
2329
2330 boolean added_separator = FALSE;
2331 while ( (node = (Node*)li.getNext()) )
2332 {
2333 if (!this->performing_undo) {
2334 if (!added_separator) {
2335 this->undo_list.push (new UndoSeparator(this));
2336 added_separator = TRUE;
2337 }
2338 this->undo_list.push (new UndoRepeatableTab(this, node, adding, input));
2339 }
2340 if (adding) {
2341 if (input && node->isInputRepeatable()) {
2342 r = r && node->addInputRepeats();
2343 } else if (!input && node->isOutputRepeatable()) {
2344 r = r && node->addOutputRepeats();
2345 }
2346 } else {
2347 if (input && node->hasRemoveableInput()) {
2348 r = r && node->removeInputRepeats();
2349 } else if (!input && node->hasRemoveableOutput()) {
2350 r = r && node->removeOutputRepeats();
2351 }
2352 }
2353 }
2354
2355 if (r && !input)
2356 this->deferrableCommandActivation->requestAction(NULL);
2357
2358 delete l;
2359
2360 // this->setCommandActivation() doesn't run often enough to deal
2361 // with accelerators.
2362 if ((added_separator) && (!this->undoCmd->isActive()))
2363 this->setUndoActivation();
2364
2365 return r;
2366 }
2367
setSelectedNodeTabVisibility(boolean v)2368 boolean EditorWindow::setSelectedNodeTabVisibility(boolean v)
2369 {
2370 List *l = this->makeSelectedNodeList();
2371 if (l == NULL || l->getSize() == 0) {
2372 if (l) delete l;
2373 return TRUE;
2374 }
2375
2376 ListIterator li(*l);
2377 Node *node;
2378 #if WORKSPACE_PAGES
2379 this->beginPageChange();
2380 #else
2381 this->beginNetworkChange();
2382 #endif
2383 boolean added_separator = FALSE;
2384 while( (node = (Node*)li.getNext()) )
2385 {
2386 node->setAllInputsVisibility(v);
2387 node->setAllOutputsVisibility(v);
2388 }
2389 delete l;
2390 #if WORKSPACE_PAGES
2391 this->endPageChange();
2392 #else
2393 this->endNetworkChange();
2394 #endif
2395
2396 return TRUE;
2397 }
2398
2399 //
2400 // Do node selection.
2401 //
selectConnection(int dir,boolean connected)2402 boolean EditorWindow::selectConnection(int dir, boolean connected)
2403 {
2404 List *l = this->makeSelectedNodeList();
2405
2406 if (l == NULL || l->getSize() == 0) {
2407 if (l) delete l;
2408 return FALSE;
2409 }
2410
2411 ListIterator li(*l);
2412 ListIterator iterator;
2413 Node *node, *snode;
2414 List *nlist = &this->network->nodeList;
2415 int nsize = nlist->getSize();
2416 int i, pos;
2417 boolean *mark = new boolean[nsize];
2418
2419 if (connected)
2420 this->deselectAllNodes();
2421 else
2422 this->selectAllNodes();
2423
2424 while((snode = (Node*)li.getNext())
2425 AND (pos = nlist->getPosition((const void*)snode)))
2426 {
2427 for(i=0; i<nsize; i++)
2428 mark[i] = FALSE;
2429
2430 /*mnodes =*/ this->network->connectedNodes(mark, pos-1, dir);
2431
2432 pos = 0;
2433 FOR_EACH_NETWORK_NODE(this->network, node, iterator)
2434 {
2435 if(mark[pos++])
2436 node->getStandIn()->setSelected(connected);
2437 }
2438 }
2439 delete mark;
2440 delete l;
2441
2442 return TRUE;
2443
2444 }
2445
2446
2447 //
2448 // Implements the 'Select Downward' command.
2449 //
selectDownwardNodes()2450 boolean EditorWindow::selectDownwardNodes()
2451 {
2452 return this->selectConnection(1, TRUE);
2453 }
2454 //
2455 // Implements the 'Select Upward' command.
2456 //
selectUpwardNodes()2457 boolean EditorWindow::selectUpwardNodes()
2458 {
2459 return this->selectConnection(-1, TRUE);
2460 }
2461 //
2462 // Implements the 'Select Connected' command.
2463 //
selectConnectedNodes()2464 boolean EditorWindow::selectConnectedNodes()
2465 {
2466 return this->selectConnection(0, TRUE);
2467 }
2468 //
2469 // Implements the 'Selected Unconnected' command.
2470 //
selectUnconnectedNodes()2471 boolean EditorWindow::selectUnconnectedNodes()
2472 {
2473 return this->selectConnection(0, FALSE);
2474 }
2475
2476 //
2477 // look through the network list for selected nodes
2478 // and open the configuration dialog associated with
2479 // the node.
2480 //
2481 #define MAX_SANE_CDBS 5
openSelectedNodesCDB()2482 void EditorWindow::openSelectedNodesCDB()
2483 {
2484 Node *node;
2485 StandIn *standIn;
2486 ListIterator iterator;
2487 int selected_count = 0;
2488
2489 //
2490 // The sanity check is to prevent opening too many cdbs at once. This path
2491 // results from Ctrl-F in the vpe and is seldom used incorrectly. The real
2492 // problem is double clicking on a node in the vpe. But when we go down that
2493 // path in the code, we don't know if we'll open a cdb or something else so
2494 // it's hard to count them up first.
2495 //
2496 FOR_EACH_NETWORK_NODE(this->network, node, iterator) {
2497 standIn = node->getStandIn();
2498 #if WORKSPACE_PAGES
2499 if (!standIn) continue;
2500 #endif
2501 if (standIn->isSelected())
2502 selected_count++;
2503 }
2504 //
2505 // Sanity check
2506 //
2507 if (selected_count > MAX_SANE_CDBS) {
2508 char msg[128];
2509 sprintf (msg, "Really open %d configuration dialogs?", selected_count);
2510 int response = theQuestionDialogManager->userQuery(this->getRootWidget(),
2511 msg, "Confirm Open CDB", "Yes", "No", NULL, 2
2512 );
2513 if (response != QuestionDialogManager::OK) return ;
2514 }
2515
2516 FOR_EACH_NETWORK_NODE(this->network, node, iterator) {
2517 standIn = node->getStandIn();
2518 #if WORKSPACE_PAGES
2519 if (!standIn) continue;
2520 #endif
2521 if (standIn->isSelected())
2522 node->openConfigurationDialog(this->getRootWidget());
2523
2524 }
2525
2526 }
2527 //
2528 // look through the network list for selected nodes
2529 // and ask the node to do its default action.
2530 //
doSelectedNodesDefaultAction()2531 void EditorWindow::doSelectedNodesDefaultAction()
2532 {
2533 Node *node;
2534 StandIn *standIn;
2535 ListIterator iterator;
2536
2537 //
2538 // The sanity check is to prevent opening too many cdbs at once. This path
2539 // results from a double click in the vpe and is often used incorrectly.
2540 //
2541 int cdb_count = 0;
2542 FOR_EACH_NETWORK_NODE(this->network, node, iterator) {
2543 standIn = node->getStandIn();
2544 #if WORKSPACE_PAGES
2545 if (!standIn) continue;
2546 #endif
2547 if (standIn->isSelected())
2548 if (node->defaultWindowIsCDB())
2549 cdb_count++;
2550 }
2551 //
2552 // Sanity check
2553 //
2554 if (cdb_count > MAX_SANE_CDBS) {
2555 char msg[128];
2556 sprintf (msg, "Really open %d configuration dialogs?", cdb_count);
2557 int response = theQuestionDialogManager->userQuery(this->getRootWidget(),
2558 msg, "Confirm Open CDB", "Yes", "No", NULL, 2
2559 );
2560 if (response != QuestionDialogManager::OK) return ;
2561 }
2562
2563 //
2564 // If there are selected interactor nodes, then deselect all
2565 // InteractorInstances in the existing control panels.
2566 //
2567 FOR_EACH_NETWORK_NODE(this->network, node, iterator) {
2568 if (node->isA(ClassInteractorNode)) {
2569 int count = network->getPanelCount();
2570 if (count != 0) {
2571 int i;
2572 for (i=1; i<=count ; i++) {
2573 ControlPanel *cp = network->getPanelByIndex(i);
2574 cp->selectAllInstances(FALSE);
2575 }
2576 }
2577 break;
2578 }
2579 }
2580
2581
2582 //
2583 // Erase any notion of the current control panel so that selected
2584 // InteractorNodes can add themselves to what will be a newly created
2585 // ControlPanel via this->getCurrentControlPanel().
2586 //
2587 this->currentPanel = NULL;
2588
2589 theApplication->setBusyCursor(TRUE);
2590 FOR_EACH_NETWORK_NODE(this->network, node, iterator) {
2591 standIn = node->getStandIn();
2592 #if WORKSPACE_PAGES
2593 if (!standIn) continue;
2594 #endif
2595 if (standIn->isSelected()) {
2596 node->openDefaultWindow(this->getRootWidget());
2597 ConfigurationDialog *cdb = node->getConfigurationDialog();
2598 if (cdb) {
2599 Widget cdbWidget = cdb->getRootWidget();
2600 if (cdbWidget) {
2601 // Transfer Accelerations
2602 TransferAccelerator(cdbWidget,
2603 this->saveOption->getRootWidget(), "ArmAndActivate");
2604 TransferAccelerator(cdbWidget,
2605 this->addInputTabOption->getRootWidget(), "ArmAndActivate");
2606 TransferAccelerator(cdbWidget,
2607 this->removeInputTabOption->getRootWidget(), "ArmAndActivate");
2608 TransferAccelerator(cdbWidget,
2609 this->executeOnceOption->getRootWidget(), "ArmAndActivate");
2610 TransferAccelerator(cdbWidget,
2611 this->executeOnChangeOption->getRootWidget(), "ArmAndActivate");
2612 TransferAccelerator(cdbWidget,
2613 this->endExecutionOption->getRootWidget(), "ArmAndActivate");
2614 }
2615 }
2616 }
2617 }
2618
2619
2620 //
2621 // Open the default windows for any selected decorators.
2622 //
2623 Decorator *decor;
2624 FOR_EACH_NETWORK_DECORATOR(this->network, decor, iterator) {
2625 if ((decor->isSelected()) && (decor->hasDefaultWindow()))
2626 decor->openDefaultWindow();
2627 }
2628
2629
2630 theApplication->setBusyCursor(FALSE);
2631
2632 }
2633
getNodeSelectionCount(const char * classname)2634 int EditorWindow::getNodeSelectionCount(const char *classname)
2635 {
2636 Node *node;
2637 StandIn *standIn;
2638 ListIterator iterator;
2639 int selected = 0;
2640
2641 FOR_EACH_NETWORK_NODE(this->network, node, iterator) {
2642 standIn = node->getStandIn();
2643 if ((standIn) && (standIn->isSelected() &&
2644 ((classname == NULL) || node->isA(classname))))
2645 selected++;
2646 }
2647 return selected;
2648 }
2649 //
2650 // look through the network list and make a list of selected nodes of
2651 // the given class. If classname == NULL, then get all selected nodes.
2652 // If no selected interactors were found then NULL is returned.
2653 //
makeSelectedNodeList(const char * classname)2654 List *EditorWindow::makeSelectedNodeList(const char *classname)
2655 {
2656 List *l;
2657 List *selected = NULL;;
2658
2659 if (classname == NULL)
2660 l = &this->network->nodeList;
2661 else
2662 l = this->network->makeClassifiedNodeList(classname);
2663
2664 if (l) {
2665 ListIterator iterator(*l);
2666 Node *node;
2667 while ( (node = (Node*)iterator.getNext()) ) {
2668 StandIn *standIn = node->getStandIn();
2669 if (standIn && standIn->isSelected()) {
2670 if (!selected)
2671 selected = new List();
2672 selected->appendElement((const void*) node);
2673 }
2674 }
2675 if (classname != NULL)
2676 delete l;
2677 }
2678 return selected;
2679 }
2680
2681
2682 List *
makeSelectedDecoratorList()2683 EditorWindow::makeSelectedDecoratorList()
2684 {
2685 Decorator *decor;
2686 ListIterator it;
2687
2688 List *selected = NULL;
2689
2690 FOR_EACH_NETWORK_DECORATOR(this->network, decor, it) {
2691 if (decor->isSelected()) {
2692 if (!selected) selected = new List;
2693 selected->appendElement((const void*)decor);
2694 }
2695 }
2696 return selected;
2697 }
2698
2699 //
2700 // Make a sorted list of modules existing in the VPE.
2701 //
makeModuleList()2702 List *EditorWindow::makeModuleList()
2703 {
2704 Node *node;
2705 ListIterator li,iterator;
2706 List *l = NUL(List*);
2707 char *name, *module;
2708 int r, i;
2709
2710 FOR_EACH_NETWORK_NODE(this->network, node, iterator)
2711 {
2712 if (!l)
2713 l = new List;
2714
2715 name = (char*)node->getNameString();
2716 li.setList(*l);
2717 i = 1; r = 1;
2718 while( (module = (char*)li.getNext()) )
2719 {
2720 r = strcmp(module, name);
2721 if(r >= 0) break;
2722 i++;
2723 }
2724 if(r != 0)
2725 {
2726 name = DuplicateString(node->getNameString());
2727 l->insertElement((const void*)name, i);
2728 }
2729 }
2730 return l;
2731 }
2732
2733 //
2734 // Notify the source and destination standIn that an arc
2735 // has been added.
2736 //
2737
notifyArk(Ark * a,boolean added)2738 void EditorWindow::notifyArk(Ark *a, boolean added)
2739 {
2740 StandIn *standIn;
2741 Node *n;
2742 int param;
2743
2744 n = a->getSourceNode(param);
2745 standIn = n->getStandIn();
2746 #if WORKSPACE_PAGES
2747 if (!standIn) return ;
2748 #endif
2749 if (added) {
2750 standIn->addArk(this, a);
2751 }
2752 if ((!this->performing_undo) && (!this->creating_new_network)) {
2753 this->undo_list.push (new UndoSeparator(this));
2754 this->undo_list.push (new UndoAddArk(this, a, added));
2755 // this->setCommandActivation() doesn't run often enough to deal
2756 // with accelerators.
2757 if (!this->undoCmd->isActive())
2758 this->setUndoActivation();
2759 }
2760 }
2761
2762 //
2763 // Move the workSpace inside the scrolled window so that the given x,y
2764 // position is at the upper left corner of the scrolled window unless
2765 // centered is TRUE in which case x,y is the center of the scrolled
2766 // window.
2767 //
moveWorkspaceWindow(int x,int y,boolean centered)2768 void EditorWindow::moveWorkspaceWindow(int x, int y, boolean centered)
2769 {
2770 ASSERT(!centered);// Not implemented yet.
2771
2772 XmScrolledWindowWidget scrollWindow;
2773 int value;
2774 int size;
2775 int max;
2776 int min;
2777 int delta;
2778 int pdelta;
2779 int newValue;
2780
2781 /*
2782 * Convert scrolled window widget to its internal form.
2783 */
2784 scrollWindow = (XmScrolledWindowWidget)this->getScrolledWindow();
2785
2786 //
2787 // Set ScrollBar's value.
2788 // ...but ensure that the values are legal, making any necessary
2789 // adjustments. That way callers (like InsertNetworkDialog) don't
2790 // need carnal knowledge of the scrollbars to1 change screen positioning.
2791 //
2792 XmScrollBarGetValues((Widget)scrollWindow->swindow.hScrollBar,
2793 &value, &size, &delta, &pdelta);
2794 XtVaGetValues ((Widget)scrollWindow->swindow.hScrollBar,
2795 XmNmaximum, &max, XmNminimum, &min, NULL);
2796
2797 if (x>= (max-size))
2798 newValue = max-(size+1);
2799 else
2800 newValue = x;
2801 newValue = MAX(min,newValue);
2802
2803
2804 XmScrollBarSetValues((Widget)scrollWindow->swindow.hScrollBar,
2805 newValue, size, delta, pdelta, True);
2806
2807 XmScrollBarGetValues((Widget)scrollWindow->swindow.vScrollBar,
2808 &value, &size, &delta, &pdelta);
2809 XtVaGetValues ((Widget)scrollWindow->swindow.vScrollBar,
2810 XmNmaximum, &max, XmNminimum, &min, NULL);
2811
2812 if (y>= (max-size))
2813 newValue = max-(size+1);
2814 else
2815 newValue = y;
2816 newValue = MAX(min,newValue);
2817
2818 XmScrollBarSetValues((Widget)scrollWindow->swindow.vScrollBar,
2819 newValue, size, delta, pdelta, True);
2820 }
2821
getWorkspaceWindowPos(int * x,int * y)2822 void EditorWindow::getWorkspaceWindowPos(int *x, int *y)
2823 {
2824 XmScrolledWindowWidget scrollWindow;
2825 int value;
2826 int size;
2827 int delta;
2828 int pdelta;
2829
2830 scrollWindow = (XmScrolledWindowWidget)this->getScrolledWindow();
2831 XmScrollBarGetValues((Widget)scrollWindow->swindow.hScrollBar,
2832 &value, &size, &delta, &pdelta);
2833 *x = value;
2834 XmScrollBarGetValues((Widget)scrollWindow->swindow.vScrollBar,
2835 &value, &size, &delta, &pdelta);
2836 *y = value;
2837 return ;
2838 }
2839
2840 //
2841 // moveWorkspaceWindow() used to do some side effect stuff on behalf
2842 // of the FindToolDialog. I've moved that into a separate method. I
2843 // hope it's clearer. The stuff in moveWorkspaceWindow was broken when
2844 // I added vpe pages because the timing of the operations changed.
2845 //
checkPointForFindDialog(FindToolDialog * dialog)2846 void EditorWindow::checkPointForFindDialog(FindToolDialog* dialog)
2847 {
2848 XmScrolledWindowWidget scrollWindow;
2849 Arg arg[8];
2850 Cardinal n;
2851 int hScrollValue;
2852 int vScrollValue;
2853
2854 ASSERT (dialog->isManaged());
2855
2856 int page = this->workSpace->getCurrentPage();
2857 EditorWorkSpace *current_ews = this->workSpace;
2858 if (page) current_ews = (EditorWorkSpace*)this->workSpace->getElement(page);
2859 GroupRecord* grec = this->getGroupOfWorkSpace(current_ews);
2860 if (this->find_restore_page)
2861 delete this->find_restore_page;
2862 if (grec)
2863 this->find_restore_page = DuplicateString(grec->getName());
2864 else
2865 this->find_restore_page = NUL(char*);
2866
2867 /*
2868 * Convert scrolled window widget to its internal form.
2869 */
2870 scrollWindow = (XmScrolledWindowWidget)this->getScrolledWindow();
2871 /*
2872 * Get drawing window resources.
2873 */
2874 n = 0;
2875 XtSetArg(arg[n], XmNvalue, &hScrollValue); n++;
2876 XtGetValues((Widget)scrollWindow->swindow.hScrollBar, arg, n);
2877
2878 n = 0;
2879 XtSetArg(arg[n], XmNvalue, &vScrollValue); n++;
2880 XtGetValues((Widget)scrollWindow->swindow.vScrollBar, arg, n);
2881
2882 /*
2883 * Store the original position. The original vpe page
2884 * was recorded earlier in this method just prior to
2885 * selecting the vpe page of the destination node.
2886 */
2887 this->Ox = hScrollValue;
2888 this->Oy = vScrollValue;
2889 }
2890
moveWorkspaceWindow(UIComponent * si)2891 void EditorWindow::moveWorkspaceWindow(UIComponent* si)
2892 {
2893 XmScrolledWindowWidget scrollWindow;
2894 Arg arg[8];
2895 Cardinal n;
2896 int hSliderSize;
2897 int vSliderSize;
2898 int hScrollValue;
2899 int vScrollValue;
2900 int hScrollMax;
2901 int vScrollMax;
2902 int newOx;
2903 int newOy;
2904
2905
2906 #if WORKSPACE_PAGES
2907 //
2908 // Present the proper page for this standin
2909 //
2910 // It's also possible to find the proper page using Node methods but we
2911 // don't ordinarily know the node behind a standin because that's protected info.
2912 //
2913 if (si) {
2914 Widget page_parent = XtParent(si->getRootWidget());
2915 if (page_parent != this->workSpace->getRootWidget()) {
2916 DictionaryIterator di(*this->pageSelector);
2917 EditorWorkSpace* ews;
2918 while ( (ews = (EditorWorkSpace*)di.getNextDefinition()) ) {
2919 if (ews->getRootWidget() == page_parent) {
2920 ews->unsetRecordedScrollPos();
2921 this->workSpace->showWorkSpace(ews);
2922 break;
2923 }
2924 }
2925 }
2926 }
2927 #endif
2928
2929 /*
2930 * Convert scrolled window widget to its internal form.
2931 */
2932 scrollWindow = (XmScrolledWindowWidget)this->getScrolledWindow();
2933 /*
2934 * Get drawing window resources.
2935 */
2936 n = 0;
2937 XtSetArg(arg[n], XmNvalue, &hScrollValue); n++;
2938 XtSetArg(arg[n], XmNsliderSize, &hSliderSize); n++;
2939 XtSetArg(arg[n], XmNmaximum, &hScrollMax); n++;
2940 XtGetValues((Widget)scrollWindow->swindow.hScrollBar, arg, n);
2941
2942 n = 0;
2943 XtSetArg(arg[n], XmNvalue, &vScrollValue); n++;
2944 XtSetArg(arg[n], XmNsliderSize, &vSliderSize); n++;
2945 XtSetArg(arg[n], XmNmaximum, &vScrollMax); n++;
2946 XtGetValues((Widget)scrollWindow->swindow.vScrollBar, arg, n);
2947
2948 /*
2949 * Check if the module is already in the clip window.
2950 */
2951
2952 int xpos, ypos, width, height;
2953 if (si) {
2954 si->getXYSize(&width, &height);
2955 si->getXYPosition(&xpos, &ypos);
2956 if ( (xpos + width < hSliderSize + hScrollValue) &&
2957 (ypos + height< vSliderSize + vScrollValue) &&
2958 (xpos > hScrollValue) &&
2959 (ypos > vScrollValue))
2960 return;
2961 }
2962
2963 /*
2964 * Calculate new origin.
2965 */
2966 if (!si) /* RESTORE */
2967 {
2968 newOx = this->Ox;
2969 newOy = this->Oy;
2970 this->Ox = -1;
2971 if (this->find_restore_page) {
2972 EditorWorkSpace* ews = (EditorWorkSpace*)
2973 this->pageSelector->findDefinition (this->find_restore_page);
2974 if (ews) this->workSpace->showWorkSpace(ews);
2975 } else {
2976 // It could be that the original was the "Untitled" page in
2977 // which case find_restore_page would legitimatly be NUL.
2978 // In that situation we can show the root workspace but only
2979 // if we first ensure that the user hasn't deleted it.
2980 // Anytime the user has deleted the page we're looking for, we
2981 // just silently ignore the problem.
2982 EditorWorkSpace* ews = (EditorWorkSpace*)
2983 this->pageSelector->findDefinition ("Untitled");
2984 if (ews) this->workSpace->showWorkSpace(ews);
2985 }
2986 this->find_restore_page = NUL(char*);
2987 }
2988 else /* FIND */
2989 {
2990 if ((newOx = xpos + width/2-hSliderSize/2) < 0)
2991 newOx = 0;
2992 if ((newOy = ypos + height/2-vSliderSize/2) < 0)
2993 newOy = 0;
2994 }
2995
2996 if (newOx + hSliderSize > hScrollMax)
2997 newOx = hScrollMax - hSliderSize;
2998
2999 if (newOy + vSliderSize > vScrollMax)
3000 newOy = vScrollMax - vSliderSize;
3001
3002 /*
3003 * Reset the scrolled window's (x,y) origin.(??????????????)
3004 */
3005 scrollWindow->swindow.hOrigin = newOx;
3006 scrollWindow->swindow.vOrigin = newOy;
3007
3008 /*
3009 * Reset the scrolled bars physically.
3010 */
3011 XtSetArg(arg[0], XmNvalue, newOx);
3012 XtSetValues((Widget)scrollWindow->swindow.hScrollBar, arg, 1);
3013 XtSetArg(arg[0], XmNvalue, newOy);
3014 XtSetValues((Widget)scrollWindow->swindow.vScrollBar, arg, 1);
3015
3016 /*
3017 * Move the work window to reflect the new state.
3018 */
3019 XtMoveWidget(scrollWindow->swindow.WorkWindow,-newOx,-newOy);
3020
3021 }
3022
3023 #if WORKSPACE_PAGES
getGroupOfWorkSpace(EditorWorkSpace * where)3024 GroupRecord* EditorWindow::getGroupOfWorkSpace (EditorWorkSpace* where)
3025 {
3026 //
3027 // If adding to a page, then find out the page name in order to
3028 // set the group record in the added object. First fetch the group
3029 // manager, then find the name of the workspace page by looping over
3030 // the page dictionary, then fetch the group record from the manager
3031 // using the name, then set the group record into the object.
3032 //
3033 GroupRecord *grec = NUL(GroupRecord*);
3034 Symbol page_sym = theSymbolManager->getSymbol(PAGE_GROUP);
3035
3036 const char *page_name = NUL(char*);
3037 GroupManager *page_mgr = NUL(GroupManager*);
3038 ASSERT(this->pageSelector);
3039 int count = this->pageSelector->getSize();
3040 int i;
3041 for (i=1; i<=count; i++) {
3042 if (where == this->pageSelector->getDefinition(i)) {
3043 page_name = this->pageSelector->getStringKey(i);
3044 break;
3045 }
3046 }
3047 page_mgr = (GroupManager*)
3048 this->network->getGroupManagers()->findDefinition(page_sym);
3049 ASSERT(page_mgr);
3050 if (page_name) {
3051 if (where != this->workSpace) {
3052 ASSERT(page_name);
3053 }
3054
3055 //
3056 // grec could be NULL for the root page when the name is still Untitled.
3057 //
3058 grec = page_mgr->getGroup (page_name);
3059 if (where != this->workSpace) {
3060 ASSERT(grec);
3061 }
3062 }
3063
3064 return grec;
3065 }
3066 #endif
3067
3068 //
3069 // Add the current ToolSelector node to the workspace
3070 //
addCurrentNode(int x,int y,EditorWorkSpace * where,boolean stitch)3071 void EditorWindow::addCurrentNode(int x, int y, EditorWorkSpace *where, boolean stitch)
3072 {
3073 NodeDefinition *nodeDef = this->toolSelector->getCurrentSelection();
3074
3075 if (nodeDef) {
3076 this->addNode(nodeDef, x, y, where);
3077 } else if (this->addingDecorators) {
3078
3079 // Deselect all currently selected nodes
3080 this->deselectAllNodes();
3081
3082 ListIterator it(*this->addingDecorators);
3083 VPEAnnotator *dec;
3084 while ( (dec = (VPEAnnotator*)it.getNext()) ) {
3085 dec->setXYPosition(x,y);
3086 dec->manage(where);
3087 dec->setSelected(TRUE);
3088 this->network->addDecoratorToList((void*)dec);
3089 #if WORKSPACE_PAGES
3090 GroupRecord* grec = this->getGroupOfWorkSpace(where);
3091 Symbol page_sym = theSymbolManager->getSymbol(PAGE_GROUP);
3092 if (grec)
3093 dec->setGroupName(grec, page_sym);
3094 #endif
3095 }
3096 this->resetCursor();
3097 this->setCommandActivation();
3098 } else if (this->pendingPaste) {
3099 // because of stitching, we might be adding nodes to a page that
3100 // isn't the current page. So, make sure the destination page
3101 // is set to the current page.
3102 if (stitch) {
3103 List *all_nodes = this->pendingPaste->makeClassifiedNodeList(ClassNode);
3104 Symbol psym = theSymbolManager->getSymbol(PAGE_GROUP);
3105 Node* any_node = NUL(Node*);
3106 const char* group_name = NUL(const char*);
3107 if ((all_nodes) && (all_nodes->getSize() >= 1)) {
3108 any_node = (Node*)all_nodes->getElement(1);
3109 group_name = any_node->getGroupName(psym);
3110 }
3111 if (!any_node) {
3112 List* all_decs = (List*)this->pendingPaste->getDecoratorList();
3113 VPEAnnotator* any_dec = NUL(VPEAnnotator*);
3114 if ((all_decs) && (all_decs->getSize() >= 1)) {
3115 any_dec = (VPEAnnotator*)all_decs->getElement(1);
3116 group_name = any_dec->getGroupName(psym);
3117 }
3118 }
3119 if (group_name) {
3120 EditorWorkSpace* ews = (EditorWorkSpace*)
3121 this->pageSelector->findDefinition(group_name);
3122 if (ews != NUL(EditorWorkSpace*))
3123 this->pageSelector->selectPage(ews);
3124 }
3125 delete all_nodes;
3126 }
3127
3128 // Deselect all currently selected nodes
3129 this->deselectAllNodes();
3130
3131 this->pendingPaste->setTopLeftPos (x,y);
3132 List *l = this->pendingPaste->getNonEmptyPanels();
3133 this->pagifyNetNodes (this->pendingPaste, where, TRUE);
3134 boolean tmp = this->creating_new_network;
3135 this->creating_new_network = TRUE;
3136 this->network->mergeNetworks (this->pendingPaste, l, TRUE, stitch);
3137 this->creating_new_network = tmp;
3138 if (l) delete l;
3139 this->resetCursor();
3140 this->setCommandActivation();
3141 }
3142
3143 //
3144 // Check these 2 fields for deletion apart from the other if blocks
3145 // because if you're adding a new node, then you still need to come
3146 // here and delete these objects.
3147 //
3148 if (this->addingDecorators) {
3149 delete this->addingDecorators;
3150 this->addingDecorators = 0;
3151 }
3152
3153 if (this->pendingPaste) {
3154 delete this->pendingPaste;
3155 this->pendingPaste = NUL(Network*);
3156 }
3157 }
3158
3159 //
3160 // Add a node of the specified type to the workspace
3161 //
addNode(NodeDefinition * nodeDef,int x,int y,EditorWorkSpace * where)3162 void EditorWindow::addNode (NodeDefinition *nodeDef, int x, int y, EditorWorkSpace *where)
3163 {
3164 Node *node;
3165
3166 // Reset the cursor if further placements are not allowed.
3167 if (!this->toolSelector->isSelectionLocked()) {
3168 this->resetCursor();
3169 this->toolSelector->deselectAllTools();
3170 }
3171
3172 node = nodeDef->createNewNode(this->network);
3173 if (node == NULL)
3174 return;
3175
3176 #if WORKSPACE_PAGES
3177 GroupRecord* grec;
3178 if (where)
3179 grec = this->getGroupOfWorkSpace(where);
3180 else {
3181 EditorWorkSpace *ews;
3182 int page = this->workSpace->getCurrentPage();
3183 if (!page)
3184 ews = this->workSpace;
3185 else
3186 ews = (EditorWorkSpace*)this->workSpace->getElement(page);
3187 grec = this->getGroupOfWorkSpace(ews);
3188 }
3189 Symbol page_sym = theSymbolManager->getSymbol(PAGE_GROUP);
3190 if (grec)
3191 node->setGroupName(grec, page_sym);
3192 #endif
3193
3194 node->setVpePosition(x,y);
3195 this->network->addNode(node, where);
3196
3197 // Deselect all currently selected nodes
3198 this->deselectAllNodes();
3199
3200 // Select the added node
3201 StandIn *si = node->getStandIn();
3202 ASSERT(si);
3203 si->setSelected(TRUE);
3204
3205 if(this->findToolDialog AND this->findToolDialog->isManaged())
3206 this->findToolDialog->changeList();
3207
3208 this->resetExecutionList();
3209 }
3210
setCursor(int cursorType)3211 void EditorWindow::setCursor(int cursorType)
3212 {
3213
3214 // Just ask the workspace to set the cursor type
3215
3216 this->workSpace->setCursor(cursorType);
3217 }
3218
3219 //
3220 // reset the EditorWindow cursor to the default.
3221 //
resetCursor()3222 void EditorWindow::resetCursor()
3223 {
3224 this->workSpace->resetCursor();
3225 }
3226
3227
3228 //
3229 // Create a list of nodes to delete, and call deleteNodes with the list.
3230 //
removeSelectedNodes()3231 void EditorWindow::removeSelectedNodes()
3232 {
3233 Node *node;
3234 List *toDelete = NULL;
3235 StandIn *si;
3236 ListIterator iterator;
3237
3238 this->deferrableCommandActivation->deferAction();
3239
3240 //
3241 // Make a copy of the deletions so that the operation can be undone
3242 //
3243 if (!this->performing_undo) {
3244 this->undo_list.push (new UndoSeparator(this));
3245 this->undo_list.push(
3246 new UndoDeletion (this,
3247 this->makeSelectedNodeList(NUL(const char*)),
3248 this->makeSelectedDecoratorList())
3249 );
3250 // this->setCommandActivation() doesn't run often enough to deal
3251 // with accelerators.
3252 if (!this->undoCmd->isActive())
3253 this->setUndoActivation();
3254 }
3255
3256 //
3257 // Build a list of nodes and unmanage the standIns that go with them.
3258 //
3259 FOR_EACH_NETWORK_NODE(this->network, node, iterator) {
3260 si = node->getStandIn();
3261 #if WORKSPACE_PAGES
3262 if (!si) continue;
3263 #endif
3264 if (si->isSelected()) {
3265 if (!toDelete)
3266 toDelete = new List;
3267 toDelete->appendElement(node);
3268 }
3269 }
3270 if (toDelete)
3271 {
3272 this->deleteNodes(toDelete);
3273 delete toDelete;
3274 }
3275
3276 //
3277 // Delete selected decorators. A separate list isn't required.
3278 //
3279 Decorator *decor;
3280 FOR_EACH_NETWORK_DECORATOR (this->network, decor, iterator) {
3281 if (decor->isSelected()) {
3282 this->network->decoratorList.removeElement((void*)decor);
3283 delete decor;
3284 }
3285 }
3286
3287 this->deferrableCommandActivation->undeferAction();
3288
3289 //this->setUndoActivation();
3290 }
3291
3292 //
3293 // A public interface to deleteNodes... used by Network::replaceInputArks
3294 // so that it can let us do important work when deleting a bunch of nodes.
3295 //
removeNodes(List * toDelete)3296 void EditorWindow::removeNodes(List* toDelete)
3297 {
3298 this->deleteNodes(toDelete);
3299 }
3300
3301 //
3302 // Called by the DeleteCommand to REALLY delete the nodes.
3303 //
deleteNodes(List * toDelete)3304 void EditorWindow::deleteNodes(List *toDelete)
3305 {
3306 Node *node;
3307 ListIterator iterator;
3308 Node *nodePtr;
3309 int deleteCnt = toDelete->getSize();
3310
3311 //
3312 // don't toggle line drawing if erasing a small number of nodes.
3313 // Would it be good to check for lines entering/leaving the selected set?
3314 // If there were no such lines, then would it be unnecessary to toggle line
3315 // routing?
3316 int threshold = 5;
3317
3318 //
3319 // turn off line routing if necessary
3320 //
3321 if (deleteCnt > threshold)
3322 this->beginPageChange();
3323
3324 //
3325 // In order to maintain consistency between the yellowing of standins and
3326 // page tabs after a run time error, check each deleted node to see if its
3327 // standin is showing an error.
3328 //
3329 boolean errored_node_deleted = FALSE;
3330
3331 //
3332 // Perform the deletion
3333 //
3334 iterator.setList(*toDelete);
3335 nodePtr = (Node*)iterator.getNext();
3336 while (nodePtr != NULL) {
3337 node = nodePtr;
3338 nodePtr = (Node*)iterator.getNext();
3339 StandIn* si = node->getStandIn();
3340 if ((si) && (this->errored_standins))
3341 errored_node_deleted|= this->errored_standins->removeElement((void*)si);
3342 this->network->deleteNode(node);
3343 }
3344
3345 //
3346 // restart line routing if necessary
3347 //
3348 if (deleteCnt > threshold)
3349 this->endPageChange();
3350 this->lastSelectedTransmitter = NULL;
3351
3352 if (errored_node_deleted) {
3353 //
3354 // resetErrorList with arg==FALSE means update colors but don't
3355 // toss out the list.
3356 //
3357 this->resetErrorList(FALSE);
3358 }
3359
3360 //
3361 // Update the find tool dialog
3362 //
3363 if(this->findToolDialog AND this->findToolDialog->isManaged())
3364 this->findToolDialog->changeList();
3365 }
3366
highlightNodes(int h,List * l)3367 void EditorWindow::highlightNodes(int h, List *l)
3368 {
3369 Node *n;
3370 if (!l)
3371 l = &this->network->nodeList;
3372
3373 ListIterator li(*l);
3374 while ( (n = (Node*)li.getNext()) )
3375 this->highlightNode(n,h);
3376 }
3377
highlightNode(const char * name,int instance,int flag)3378 void EditorWindow::highlightNode(const char* name, int instance, int flag)
3379 {
3380 Node *node;
3381
3382 node = this->network->findNode(theSymbolManager->getSymbol(name),instance);
3383 if (NOT node)
3384 return;
3385
3386 this->highlightNode(node,flag);
3387 }
3388
highlightNode(Node * n,int flag)3389 void EditorWindow::highlightNode(Node *n, int flag)
3390 {
3391 Pixel color;
3392
3393 this->executing_node = NUL(Node*);
3394 StandIn* si = n->getStandIn();
3395 switch (flag)
3396 {
3397 case EditorWindow::ERRORHIGHLIGHT :
3398 color = theDXApplication->getErrorNodeForeground();
3399 if (!this->errored_standins) this->errored_standins = new List;
3400 if ((si) && (this->errored_standins->isMember((void*)si) == FALSE))
3401 this->errored_standins->appendElement((void*)si);
3402 break;
3403
3404 case EditorWindow::EXECUTEHIGHLIGHT :
3405 color = theDXApplication->getExecutionHighlightForeground();
3406 if (this->executed_nodes == NUL(List*))
3407 this->executed_nodes = new List;
3408 if (!this->executed_nodes->isMember((const void*)n))
3409 this->executed_nodes->appendElement((const void*)n);
3410 this->showExecutedCmd->activate();
3411 this->executing_node = n;
3412 break;
3413
3414 case EditorWindow::REMOVEHIGHLIGHT :
3415 color = standInGetDefaultForeground();
3416 break;
3417
3418 default:
3419
3420 ASSERT(FALSE);
3421 }
3422
3423 #if WORKSPACE_PAGES
3424 //
3425 // Notify the pageSelector to highlight the tab of the page containing
3426 // the node whose standin we're trying to hightlight.
3427 //
3428 Symbol psym = theSymbolManager->getSymbol(PAGE_GROUP);
3429 EditorWorkSpace *ews = this->workSpace;
3430 const char* group_name = n->getGroupName(psym);
3431 if (group_name) {
3432 EditorWorkSpace *page =
3433 (EditorWorkSpace*)this->pageSelector->findDefinition(group_name);
3434 ASSERT(page);
3435 ews = page;
3436 }
3437 this->pageSelector->highlightTab (ews, flag);
3438
3439 //
3440 // If the flag is ERROR, then make sure that the standin does exist
3441 // because we're going to be moving the vpe there anyway and we need
3442 // the feedback.
3443 //
3444 if ((!si) && (flag == EditorWindow::ERRORHIGHLIGHT)) {
3445 this->pageSelector->selectPage(ews);
3446 si = n->getStandIn();
3447 if (si) {
3448 if (!this->errored_standins) this->errored_standins = new List;
3449 if (this->errored_standins->isMember((void*)si) == FALSE)
3450 this->errored_standins->appendElement((void*)si);
3451 }
3452 }
3453 if (si)
3454 #endif
3455 si->setLabelColor(color);
3456 }
3457
selectDecorator(VPEAnnotator * dec,boolean select,boolean warp)3458 boolean EditorWindow::selectDecorator (VPEAnnotator* dec, boolean select, boolean warp)
3459 {
3460 if (dec->getNetwork()->getEditor() != this)
3461 return FALSE;
3462 //
3463 // Select the proper page.
3464 //
3465 Symbol psym = theSymbolManager->getSymbol(PAGE_GROUP);
3466 const char* group_name = dec->getGroupName(psym);
3467 if ((select) && (warp)) {
3468 if (group_name) {
3469 EditorWorkSpace *page =
3470 (EditorWorkSpace*)this->pageSelector->findDefinition(group_name);
3471 ASSERT(page);
3472 page->unsetRecordedScrollPos();
3473 this->pageSelector->selectPage(page);
3474 this->populatePage(page);
3475 this->workSpace->resize();
3476 } else {
3477 this->workSpace->unsetRecordedScrollPos();
3478 this->pageSelector->selectPage(this->workSpace);
3479 }
3480 } else {
3481 //
3482 // If we're not going to bring the selected node into view,
3483 // then make sure that the node's page is the current page.
3484 // If it's not, then silently refuse to select the node.
3485 //
3486 boolean wrong_page = FALSE;
3487 EditorWorkSpace *page = NUL(EditorWorkSpace*);
3488 if (group_name)
3489 page = (EditorWorkSpace*)this->pageSelector->findDefinition(group_name);
3490 else
3491 page = this->workSpace;
3492 int page_no = this->workSpace->getCurrentPage();
3493 EditorWorkSpace* current_ews = this->workSpace;
3494 if (page_no) current_ews = (EditorWorkSpace*)this->workSpace->getElement(page_no);
3495 if (page != current_ews) wrong_page = TRUE;
3496
3497 if (wrong_page)
3498 return TRUE;
3499 }
3500 dec->setSelected(select);
3501 if (select && warp)
3502 this->moveWorkspaceWindow(dec);
3503 return TRUE;
3504 }
3505
selectNode(Node * node,boolean select,boolean warp)3506 boolean EditorWindow::selectNode(Node *node, boolean select, boolean warp)
3507 {
3508 StandIn *standIn;
3509 ASSERT(node);
3510 if (node->getNetwork()->getEditor() != this)
3511 return FALSE;
3512
3513 standIn = node->getStandIn();
3514 #if WORKSPACE_PAGES
3515 //
3516 // Select the proper page.
3517 //
3518 Symbol psym = theSymbolManager->getSymbol(PAGE_GROUP);
3519 const char* group_name = node->getGroupName(psym);
3520 if ((select) && (warp)) {
3521 if (group_name) {
3522 EditorWorkSpace *page =
3523 (EditorWorkSpace*)this->pageSelector->findDefinition(group_name);
3524 ASSERT(page);
3525 page->unsetRecordedScrollPos();
3526 this->pageSelector->selectPage(page);
3527 this->populatePage(page);
3528 this->workSpace->resize();
3529 } else {
3530 this->workSpace->unsetRecordedScrollPos();
3531 this->pageSelector->selectPage(this->workSpace);
3532 ASSERT(standIn);
3533 }
3534 if (!standIn) {
3535 standIn = node->getStandIn();
3536 }
3537 ASSERT(standIn);
3538 } else if (!standIn) {
3539 return TRUE;
3540 } else {
3541 //
3542 // If we're not going to bring the selected node into view,
3543 // then make sure that the node's page is the current page.
3544 // If it's not, then silently refuse to select the node.
3545 //
3546 boolean wrong_page = FALSE;
3547 EditorWorkSpace *page = NUL(EditorWorkSpace*);
3548 if (group_name)
3549 page = (EditorWorkSpace*)this->pageSelector->findDefinition(group_name);
3550 else
3551 page = this->workSpace;
3552 int page_no = this->workSpace->getCurrentPage();
3553 EditorWorkSpace* current_ews = this->workSpace;
3554 if (page_no) current_ews = (EditorWorkSpace*)this->workSpace->getElement(page_no);
3555 if (page != current_ews) wrong_page = TRUE;
3556
3557 if (wrong_page)
3558 return TRUE;
3559 }
3560 ASSERT(standIn);
3561 #endif
3562 standIn->setSelected(select);
3563 if (select && warp)
3564 this->moveWorkspaceWindow(standIn);
3565 return TRUE;
3566
3567 }
3568
selectNode(char * name,int instance,boolean select)3569 boolean EditorWindow::selectNode(char* name, int instance, boolean select)
3570 {
3571 Node *node;
3572
3573 node = this->network->findNode(theSymbolManager->getSymbol(name),instance);
3574 if (NOT node)
3575 return (FALSE);
3576 return this->selectNode(node, select, TRUE);
3577 }
3578
3579 #define SELECT_ALL 0
3580 #define DESELECT_ALL 1
3581 #define SELECT_UNSELECTED 2
3582 #define SELECT_ALL_IN_PAGE 3
3583
selectUnselectedNodes()3584 void EditorWindow::selectUnselectedNodes()
3585 {
3586 this->selectNodes(SELECT_UNSELECTED);
3587 }
selectAllNodes()3588 void EditorWindow::selectAllNodes()
3589 {
3590 #if WORKSPACE_PAGES
3591 this->selectNodes(SELECT_ALL_IN_PAGE);
3592 #else
3593 this->selectNodes(SELECT_ALL);
3594 #endif
3595 }
deselectAllNodes()3596 void EditorWindow::deselectAllNodes()
3597 {
3598 this->selectNodes(DESELECT_ALL);
3599 }
3600
selectNodes(int how)3601 void EditorWindow::selectNodes(int how)
3602 {
3603 ListIterator li(this->network->nodeList);
3604 Node *n;
3605 EditorWorkSpace* page = this->workSpace;
3606 #if WORKSPACE_PAGES
3607 if (this->network->isDeleted()) return ;
3608 int page_num = this->workSpace->getCurrentPage();
3609 if (page_num) page = (EditorWorkSpace*)this->workSpace->getElement(page_num);
3610 #endif
3611
3612 this->deferrableCommandActivation->deferAction();
3613
3614 for(n = (Node*)li.getNext(); n; n = (Node*)li.getNext()) {
3615 StandIn *si = n->getStandIn();
3616 if (!si) continue;
3617 switch (how) {
3618 case SELECT_ALL: si->setSelected(TRUE); break;
3619 case DESELECT_ALL: si->setSelected(FALSE); break;
3620 case SELECT_UNSELECTED: si->setSelected(!si->isSelected()); break;
3621 case SELECT_ALL_IN_PAGE: if (si->getWorkSpace() == page)
3622 si->setSelected(TRUE); break;
3623 }
3624 }
3625
3626 // Decorators
3627 Decorator *decor;
3628 ListIterator iterator;
3629 FOR_EACH_NETWORK_DECORATOR (this->network, decor, iterator) {
3630 switch (how) {
3631 case SELECT_ALL: decor->setSelected(TRUE); break;
3632 case DESELECT_ALL: decor->setSelected(FALSE); break;
3633 case SELECT_UNSELECTED: decor->setSelected(!decor->isSelected()); break;
3634 case SELECT_ALL_IN_PAGE: if (decor->getWorkSpace() == page)
3635 decor->setSelected(TRUE); break;
3636 }
3637 }
3638 this->deferrableCommandActivation->undeferAction();
3639 }
3640
3641
3642
serverDisconnected()3643 void EditorWindow::serverDisconnected()
3644 {
3645 Pixel runColor = theDXApplication->getExecutionHighlightForeground();
3646 Pixel defaultColor = standInGetDefaultForeground();
3647
3648 // For each node, if the standin's forground color is "execute", reset it.
3649 Node *n;
3650 ListIterator li(this->network->nodeList);
3651 while ( (n = (Node*)li.getNext()) ) {
3652 StandIn *si = n->getStandIn();
3653 #if WORKSPACE_PAGES
3654 if (!si) continue;
3655 #endif
3656 if (si->getLabelColor() == runColor)
3657 si->setLabelColor(defaultColor);
3658 }
3659
3660
3661 this->DXWindow::serverDisconnected();
3662 this->executing_node = NUL(Node*);
3663 this->resetColorList();
3664 }
3665
postPanelGroupDialog()3666 void EditorWindow::postPanelGroupDialog()
3667 {
3668 if(NOT this->panelGroupDialog)
3669 this->panelGroupDialog
3670 = new ControlPanelGroupDialog(this->getRootWidget());
3671 this->panelGroupDialog->setData(this->network->getPanelGroupManager());
3672
3673 this->panelGroupDialog->post();
3674 }
3675
postProcessGroupCreateDialog()3676 void EditorWindow::postProcessGroupCreateDialog()
3677 {
3678 Network *net = this->getNetwork();
3679 Node *n;
3680 ListIterator iter;
3681 boolean hasloop = FALSE;
3682
3683 FOR_EACH_NETWORK_NODE(net,n,iter) {
3684 NodeDefinition *nd = n->getDefinition();
3685 hasloop = nd->isMDFFlagLOOP();
3686 if (hasloop)
3687 break;
3688
3689 }
3690
3691 if (hasloop) {
3692 InfoMessage("Execution groups, and thus distributed execution, can\n"
3693 "not be used in programs that have looping tools at the\n"
3694 "top level of the program. If you would like to use \n"
3695 "distributed execution, encapsulate your loops within\n"
3696 "macros and then create the execution groups.");
3697 } else {
3698 if(NOT this->processGroupCreateDialog)
3699 this->processGroupCreateDialog
3700 = new ProcessGroupCreateDialog(this);
3701
3702 this->processGroupCreateDialog->post();
3703 }
3704 }
3705
3706 #if WORKSPACE_PAGES
setGroup(GroupRecord * grec,Symbol groupID)3707 void EditorWindow::setGroup(GroupRecord *grec, Symbol groupID)
3708 {
3709 //
3710 // Do all Nodes
3711 //
3712 List *nlist = this->makeSelectedNodeList();
3713
3714 if (nlist) {
3715 ListIterator li(*nlist);
3716 Node *node;
3717
3718 while( (node = (Node*)li.getNext()) )
3719 node->setGroupName(grec, groupID);
3720
3721 delete nlist;
3722 }
3723
3724 //
3725 // Do all Decorators
3726 //
3727 List *seldec = this->makeSelectedDecoratorList();
3728 if (seldec) {
3729 ListIterator li(*seldec);
3730 VPEAnnotator *vpea;
3731 while ( (vpea = (VPEAnnotator*)li.getNext()) )
3732 vpea->setGroupName(grec, groupID);
3733
3734 delete seldec;
3735 }
3736
3737 }
3738
resetGroup(const char * name,Symbol groupID)3739 void EditorWindow::resetGroup(const char* name, Symbol groupID)
3740 {
3741 Node *node;
3742 ListIterator li;
3743
3744 FOR_EACH_NETWORK_NODE(this->network, node, li)
3745 {
3746 const char *s = node->getGroupName(groupID);
3747 if(s && EqualString(name, s))
3748 node->setGroupName(NUL(GroupRecord*), groupID);
3749 }
3750
3751 //
3752 // Do all Decorators
3753 //
3754 Decorator* dec;
3755 FOR_EACH_NETWORK_DECORATOR(this->network, dec, li) {
3756 VPEAnnotator *vpea = (VPEAnnotator*)dec;
3757 const char *s = vpea->getGroupName(groupID);
3758 if(s && EqualString(name, s))
3759 vpea->setGroupName(NUL(GroupRecord*), groupID);
3760 }
3761
3762 }
3763
selectGroup(const char * name,Symbol groupID)3764 void EditorWindow::selectGroup(const char* name, Symbol groupID)
3765 {
3766 Node *node, *firstNode = NUL(Node*);
3767 ListIterator li;
3768
3769 this->deselectAllNodes();
3770
3771 FOR_EACH_NETWORK_NODE(this->network, node, li)
3772 {
3773 const char *s = node->getGroupName(groupID);
3774 if(s && EqualString(name, s))
3775 {
3776 if (firstNode == NUL(Node*)) {
3777 this->selectNode(node, TRUE, TRUE);
3778 firstNode = node;
3779 } else
3780 this->selectNode(node, TRUE, FALSE);
3781 }
3782 }
3783
3784 //
3785 // Do all Decorators
3786 //
3787 Decorator* dec;
3788 FOR_EACH_NETWORK_DECORATOR(this->network, dec, li) {
3789 VPEAnnotator *vpea = (VPEAnnotator*)dec;
3790 const char *group_name = vpea->getGroupName(groupID);
3791 if ((group_name) && (EqualString(group_name, name))) {
3792 vpea->setSelected(TRUE);
3793 } else {
3794 vpea->setSelected(FALSE);
3795 }
3796 }
3797
3798 if(NOT firstNode)
3799 WarningMessage("Process group %s is empty.", name);
3800 }
3801
clearGroup(const char * name,Symbol groupID)3802 void EditorWindow::clearGroup(const char* name, Symbol groupID)
3803 {
3804 Node *node;
3805 ListIterator li;
3806
3807 FOR_EACH_NETWORK_NODE(this->network, node, li)
3808 node->setGroupName(NULL, groupID);
3809
3810 //
3811 // Do all Decorators
3812 //
3813 Decorator* dec;
3814 FOR_EACH_NETWORK_DECORATOR(this->network, dec, li) {
3815 VPEAnnotator *vpea = (VPEAnnotator*)dec;
3816 vpea->setGroupName(NUL(GroupRecord*), groupID);
3817 }
3818 }
3819
3820 //
3821 // Look for the definition of the old group and change dictionary entries so
3822 // that members of that group belong to the new group. If old_group doesn't
3823 // currently exist, then treat nodes as if they belong if they have no group name.
3824 //
3825 boolean
changeGroup(const char * old_group,const char * new_group,Symbol groupID)3826 EditorWindow::changeGroup (const char* old_group, const char* new_group, Symbol groupID)
3827 {
3828 GroupManager *gmgr = (GroupManager*)
3829 this->network->getGroupManagers()->findDefinition(groupID);
3830 GroupRecord* old_grec = gmgr->getGroup(old_group);
3831
3832 //
3833 // If there is an existing group with this name then we'll fail here, but that
3834 // should have been tested for earlier.
3835 //
3836 GroupRecord* new_grec = gmgr->getGroup(new_group);
3837 if (new_grec) return FALSE;
3838
3839 //
3840 // The call to GroupManager::createGroup() will produce a call
3841 // to EditorWindow::setGroup(). So, if you're changing a group and something
3842 // is already selected in the vpe, then that thing will be in the new group
3843 // as soon as we come back from createGroup.
3844 //
3845 if (!gmgr->createGroup (new_group, this->network)) return FALSE;
3846 ASSERT (new_grec = gmgr->getGroup(new_group));
3847
3848 Node* node;
3849 ListIterator li;
3850 FOR_EACH_NETWORK_NODE(this->network, node, li) {
3851 const char* group_name = node->getGroupName(groupID);
3852 if ((group_name) && (EqualString(group_name, old_group))) {
3853 node->setGroupName(new_grec, groupID);
3854 } else if ((!group_name) && (!old_grec)) {
3855 node->setGroupName(new_grec, groupID);
3856 }
3857 }
3858 Decorator* dec;
3859 FOR_EACH_NETWORK_DECORATOR(this->network, dec, li) {
3860 VPEAnnotator* vpea = (VPEAnnotator*)dec;
3861 const char* group_name = vpea->getGroupName(groupID);
3862 if ((group_name) && (EqualString(group_name, old_group))) {
3863 vpea->setGroupName(new_grec, groupID);
3864 } else if ((!group_name) && (!old_grec)) {
3865 vpea->setGroupName(new_grec, groupID);
3866 }
3867 }
3868 if (old_grec) {
3869 ASSERT(gmgr->removeGroup (old_group, this->network));
3870 }
3871 return TRUE;
3872 }
3873
3874 #else
setProcessGroup(const char * name)3875 void EditorWindow::setProcessGroup(const char* name)
3876 {
3877 List *nlist = this->makeSelectedNodeList();
3878
3879 if(NOT nlist) return;
3880
3881 ListIterator li(*nlist);
3882 Node *node;
3883
3884 while(node = (Node*)li.getNext())
3885 node->setGroupName(name);
3886
3887 delete nlist;
3888 }
3889
resetProcessGroup(const char * name)3890 void EditorWindow::resetProcessGroup(const char* name)
3891 {
3892 Node *node;
3893 ListIterator li;
3894
3895 FOR_EACH_NETWORK_NODE(this->network, node, li)
3896 {
3897 const char *s = node->getGroupName();
3898 if(s && EqualString(name, s))
3899 node->setGroupName(NULL);
3900 }
3901 }
3902
selectProcessGroup(const char * name)3903 void EditorWindow::selectProcessGroup(const char* name)
3904 {
3905 Node *node, *firstNode = NULL;
3906 ListIterator li;
3907
3908 this->deselectAllNodes();
3909
3910 FOR_EACH_NETWORK_NODE(this->network, node, li)
3911 {
3912 const char *s = node->getGroupName();
3913 if(s && EqualString(name, s))
3914 {
3915 if(firstNode)
3916 this->selectNode(node, TRUE, FALSE);
3917 else
3918 firstNode = node;
3919 }
3920 }
3921
3922 if(NOT firstNode)
3923 WarningMessage("Process group %s is empty.", name);
3924 else
3925 this->selectNode(firstNode, TRUE, TRUE);
3926 }
3927
clearProcessGroup(const char * name)3928 void EditorWindow::clearProcessGroup(const char* name)
3929 {
3930 Node *node;
3931 ListIterator li;
3932
3933 FOR_EACH_NETWORK_NODE(this->network, node, li)
3934 node->setGroupName(NULL);
3935 }
3936 #endif
3937
installWorkSpaceInfo(WorkSpaceInfo * info)3938 void EditorWindow::installWorkSpaceInfo(WorkSpaceInfo *info)
3939 {
3940 ASSERT(this->workSpace);
3941 this->workSpace->installInfo(info);
3942 }
3943
3944 #if WORKSPACE_PAGES
beginPageChange()3945 void EditorWindow::beginPageChange()
3946 {
3947 int page = this->workSpace->getCurrentPage();
3948 WorkSpace *current_ews = this->workSpace;
3949 if (page) current_ews = this->workSpace->getElement(page);
3950 current_ews->beginManyPlacements();
3951 this->deferrableCommandActivation->deferAction();
3952 this->resetExecutionList();
3953 }
3954
endPageChange()3955 void EditorWindow::endPageChange()
3956 {
3957 int page = this->workSpace->getCurrentPage();
3958 WorkSpace *current_ews = this->workSpace;
3959 if (page) current_ews = this->workSpace->getElement(page);
3960 current_ews->endManyPlacements();
3961 //
3962 // Don't resize if we need less space. It's too visually jarring.
3963 //
3964 int reqw, w, reqh, h;
3965 this->workSpace->getMaxWidthHeight(&reqw, &reqh);
3966 this->workSpace->getXYSize(&w,&h);
3967 if ((reqw > w) || (reqh > h)) this->workSpace->resize();
3968
3969 this->deferrableCommandActivation->requestAction(NULL);
3970 this->deferrableCommandActivation->undeferAction();
3971 }
3972 #endif
3973
3974 //
3975 // Do what ever is necessary just before changing the current network.
3976 // To make things run faster we turn off line routing. This should
3977 // be followed by a call to endNetworkChange(), which will re-enable
3978 // line routing.
3979 //
beginNetworkChange()3980 void EditorWindow::beginNetworkChange()
3981 {
3982 WorkSpace *ws = this->workSpace;
3983 ASSERT(ws);
3984 ws->beginManyPlacements();
3985 this->lastSelectedTransmitter = NULL;
3986 this->deferrableCommandActivation->deferAction();
3987 this->resetColorList();
3988 }
3989 //
3990 // Do what ever is necessary just after changing to the current network.
3991 // To make things run faster we turn off line routing in beginNetworkChange()
3992 // which should be called before this is called.
3993 //
endNetworkChange()3994 void EditorWindow::endNetworkChange()
3995 {
3996 WorkSpace *ws = this->workSpace;
3997 ASSERT(ws);
3998 this->lastSelectedTransmitter = NULL;
3999 ws->endManyPlacements();
4000
4001 #if WORKSPACE_PAGES
4002 //
4003 // All non-empty pages will be created automatically. Now go and look
4004 // for empty pages and create them.
4005 //
4006 PageGroupManager *pmgr = (PageGroupManager*)
4007 this->network->getGroupManagers()->findDefinition(PAGE_GROUP);
4008 int gcnt = pmgr->getGroupCount();
4009 if (gcnt) {
4010 int i;
4011 for (i=1; i<=gcnt; i++) {
4012 const char *pageName = pmgr->getGroupName(i);
4013 if (this->pageSelector->findDefinition (pageName)) continue;
4014 PageGroupRecord *prec = (PageGroupRecord*)pmgr->getGroup (pageName);
4015 ASSERT(prec);
4016 EditorWorkSpace *page = (EditorWorkSpace*) this->workSpace->addPage();
4017 page->resetCursor();
4018 ASSERT (this->pageSelector->addDefinition (pageName, page));
4019 }
4020 //
4021 // If the root page has no members and its name is still Untitled, then
4022 // remove the it from the page selector since there's no longer
4023 // a need for it.
4024 // On the other hande, if the root page has members, then make sure that
4025 // it's in the PageSelector.
4026 //
4027 int cnt = this->getPageMemberCount (this->workSpace);
4028 if (!cnt) {
4029 if (this->network->getFileName()) {
4030 EditorWorkSpace* ews = (EditorWorkSpace*)
4031 this->pageSelector->findDefinition("Untitled");
4032 if (this->workSpace == ews) {
4033 this->pageSelector->removeDefinition ((void*)this->workSpace);
4034
4035 //
4036 // Try to get the leftmost tab's workspace.
4037 //
4038 EditorWorkSpace* ews = (EditorWorkSpace*)
4039 this->pageSelector->getInitialWorkSpace();
4040 this->workSpace->showWorkSpace(ews);
4041 }
4042 }
4043 } else {
4044 int i,dsize = this->pageSelector->getSize();
4045 boolean found = FALSE;
4046 for (i=1; i<=dsize; i++) {
4047 EditorWorkSpace* ews = (EditorWorkSpace*)
4048 this->pageSelector->getDefinition(i);
4049 if (ews == this->workSpace) {
4050 found = TRUE;
4051 break;
4052 }
4053 }
4054 if (!found)
4055 this->pageSelector->addDefinition ("Untitled", this->workSpace);
4056 }
4057 }
4058 #endif
4059
4060 this->deferrableCommandActivation->requestAction(NULL);
4061 this->deferrableCommandActivation->undeferAction();
4062 }
4063 //
4064 // Do what ever is necessary just before and after reading a new network
4065 // These should be called in pairs.
4066 //
prepareForNewNetwork()4067 void EditorWindow::prepareForNewNetwork()
4068 {
4069
4070 if(this->findToolDialog)
4071 this->findToolDialog->unmanage();
4072
4073 if(this->printProgramDialog)
4074 this->printProgramDialog->unmanage();
4075
4076 if(this->saveAsCCodeDialog)
4077 this->saveAsCCodeDialog->unmanage();
4078
4079 if(this->processGroupCreateDialog)
4080 this->processGroupCreateDialog->unmanage();
4081
4082 if(this->panelGroupDialog)
4083 this->panelGroupDialog->unmanage();
4084
4085 if(this->panelAccessDialog)
4086 this->panelAccessDialog->unmanage();
4087
4088 #ifndef FORGET_GETSET
4089 if ((EditorWindow::GetSetDialog) && (this->isAnchor()) && (this->network))
4090 EditorWindow::GetSetDialog->unmanage();
4091 #endif
4092
4093 this->beginNetworkChange();
4094
4095 #if WORKSPACE_PAGES
4096 ListIterator it(this->network->decoratorList);
4097 Decorator* dec;
4098 while ( (dec = (Decorator*)it.getNext()) ) {
4099 if ((dec->getRootWidget()) && (dec->isManaged())) {
4100 dec->unmanage();
4101 dec->uncreateDecorator();
4102 }
4103 }
4104 this->destroyStandIns(&this->network->nodeList);
4105 if (this->pageSelector) {
4106 int i, pcnt = this->pageSelector->getSize();
4107 this->network->getGroupManagers()->findDefinition(PAGE_GROUP);
4108 for (i=1; i<=pcnt; i++) {
4109 EditorWorkSpace *ews = (EditorWorkSpace*)
4110 this->pageSelector->getDefinition(i);
4111 if (ews != this->workSpace) {
4112 WorkSpaceInfo* info = ews->getInfo();
4113 delete ews;
4114 delete info;
4115 }
4116 }
4117 this->pageSelector->clear();
4118 }
4119 this->workSpace->setMembersInitialized(FALSE);
4120 this->workSpace->showRoot();
4121 #endif
4122
4123 // reset the workspace
4124 // FIXME: shouldn't this be in completeNewNetwork()
4125 this->moveWorkspaceWindow(0,0, FALSE);
4126
4127 this->creating_new_network = TRUE;
4128 }
completeNewNetwork()4129 void EditorWindow::completeNewNetwork()
4130 {
4131 this->endNetworkChange();
4132 this->clearUndoList();
4133 this->creating_new_network = FALSE;
4134 theDXApplication->refreshErrorIndicators();
4135
4136 }
4137
4138 #ifndef FORGET_GETSET
4139 void
postGetSetConversionDialog()4140 EditorWindow::postGetSetConversionDialog()
4141 {
4142 if (!EditorWindow::GetSetDialog)
4143 EditorWindow::GetSetDialog = new GetSetConversionDialog();
4144
4145 EditorWindow::GetSetDialog->post();
4146
4147 List *glns = this->network->makeNamedNodeList ("Get");
4148 if (!glns) glns = this->network->makeNamedNodeList ("Set");
4149 if (glns) {
4150 EditorWindow::GetSetDialog->setActiveEditor(this);
4151 delete glns;
4152 }
4153 }
4154 #endif // FORGET_GETSET
4155
4156 //
4157 // Open the grid dialog
4158 //
postGridDialog()4159 void EditorWindow::postGridDialog()
4160 {
4161 if (NOT this->gridDialog )
4162 this->gridDialog = new GridDialog(this->getRootWidget(),
4163 (WorkSpace*)this->workSpace);
4164 this->gridDialog->post();
4165 }
4166 //
4167 // Open the find tool dialog
4168 //
postFindToolDialog()4169 void EditorWindow::postFindToolDialog()
4170 {
4171 if (NOT this->findToolDialog )
4172 this->findToolDialog = new FindToolDialog(this);
4173 this->findToolDialog->post();
4174 }
4175 //
4176 // Open the print program dialog
4177 //
postPrintProgramDialog()4178 void EditorWindow::postPrintProgramDialog()
4179 {
4180 if (NOT this->printProgramDialog)
4181 this->printProgramDialog = new PrintProgramDialog(this);
4182 this->printProgramDialog->post();
4183 }
4184
4185 //
4186 // Virtual function called at the beginning/end of Command::execute
4187 // We must turn off tool selection and make sure the cursor is
4188 // back to the normal cursor (i.e. not the Tool placement cursor).
4189 //
beginCommandExecuting()4190 void EditorWindow::beginCommandExecuting()
4191 {
4192 this->toolSelector->deselectAllTools();
4193 this->workSpace->resetCursor();
4194 }
4195
notifyCPChange(boolean newList)4196 void EditorWindow::notifyCPChange(boolean newList)
4197 {
4198 if(this->panelGroupDialog)
4199 {
4200 if(newList)
4201 this->panelGroupDialog->makeToggles();
4202 this->panelGroupDialog->setToggles();
4203 }
4204
4205 }
4206
notify(const Symbol message,const void * msgdata,const char * msg)4207 void EditorWindow::notify(const Symbol message, const void *msgdata, const char *msg)
4208 {
4209 if (message == DXApplication::MsgPanelChanged) {
4210 //
4211 // Set the command activations that depend on the number of panels.
4212 //
4213 int panelCount = this->network->getPanelCount();
4214 if (panelCount == 0) {
4215 this->openControlPanelByNameMenu->deactivate();
4216 this->setPanelAccessCmd->deactivate();
4217 this->setPanelGroupCmd->deactivate();
4218 } else if (panelCount == 1) {
4219 this->openControlPanelByNameMenu->activate();
4220 this->setPanelAccessCmd->activate();
4221 this->setPanelGroupCmd->activate();
4222 } // else if panelCount == 2 the commands were already activated.
4223 } else if (message == DXApplication::MsgExecute) {
4224 this->resetColorList();
4225 }
4226 this->DXWindow::notify(message, msgdata, msg);
4227 }
4228
4229
4230 //
4231 // Adjust the name of the editor window based on the current network
4232 // name.
4233 //
resetWindowTitle()4234 void EditorWindow::resetWindowTitle()
4235 {
4236 const char *vpe_name = "Visual Program Editor";
4237 char *p = NULL, *t = NULL;
4238 const char *title, *file = this->network->getFileName();
4239
4240 if (file) {
4241 p = GetFullFilePath(file);
4242 t = new char[STRLEN(p) + STRLEN(vpe_name) +3];
4243 sprintf(t,"%s: %s", vpe_name, p);
4244 #ifdef OS2
4245 if (STRLEN(t)>60)
4246 memmove(t, &t[STRLEN(t)-60],61);
4247 #endif
4248 title = t;
4249
4250 #ifndef FORGET_GETSET
4251 if (EditorWindow::GetSetDialog)
4252 EditorWindow::GetSetDialog->notifyTitleChange(this, title);
4253 #endif
4254
4255 } else {
4256 title = vpe_name;
4257 }
4258 this->setWindowTitle(title);
4259 if (p) delete p;
4260 if (t) delete t;
4261 }
4262
4263 //
4264 // Determine if there are any nodes of the give class that are selected.
4265 //
anySelectedNodes(const char * classname)4266 boolean EditorWindow::anySelectedNodes(const char *classname)
4267 {
4268 boolean r;
4269 List *l = this->makeSelectedNodeList(classname);
4270 if (!l)
4271 return FALSE;
4272
4273 if (l->getSize() != 0)
4274 r = TRUE;
4275 else
4276 r = FALSE;
4277 delete l;
4278 return r;
4279 }
4280
4281 //
4282 // Return TRUE if there are selected Macros nodes.
4283 //
anySelectedMacros()4284 boolean EditorWindow::anySelectedMacros()
4285 {
4286 return this->anySelectedNodes(ClassMacroNode);
4287 }
anySelectedDisplayNodes()4288 boolean EditorWindow::anySelectedDisplayNodes()
4289 {
4290 return this->anySelectedNodes(ClassDisplayNode);
4291 }
anySelectedColormaps()4292 boolean EditorWindow::anySelectedColormaps()
4293 {
4294 return this->anySelectedNodes(ClassColormapNode);
4295 }
openSelectedMacros()4296 void EditorWindow::openSelectedMacros()
4297 {
4298 List *l = this->makeSelectedNodeList(ClassMacroNode);
4299 if (!l)
4300 return;
4301 ListIterator li(*l);
4302
4303 MacroNode *n;
4304 while( (n = (MacroNode *)li.getNext()) ) {
4305 n->openMacro();
4306 MacroDefinition* md = (MacroDefinition*)n->getDefinition();
4307 Network* net = md->getNetwork();
4308 theDXApplication->appendReferencedFile (net->getFileName());
4309 }
4310 delete l;
4311 }
openSelectedImageWindows()4312 void EditorWindow::openSelectedImageWindows()
4313 {
4314 List *l = this->makeSelectedNodeList(ClassDisplayNode);
4315 if (!l)
4316 return;
4317 ListIterator li(*l);
4318
4319 DisplayNode *n;
4320 while( (n = (DisplayNode *)li.getNext()) )
4321 n->openImageWindow(TRUE);
4322 delete l;
4323 }
4324
4325 //
4326 // Print the visual program as a PostScript file using geometry and not
4327 // bitmaps. We set up the page so that it maps to the current workspace
4328 // and then as the StandIns and ArkStandIns to print themselves.
4329 // If the scale allows and the label_parameters arg is set, then
4330 // label the parameters and display the values.
4331 // We return FALSE and issue and error message if an error occurs.
4332 //
printVisualProgramAsPS(const char * filename,float x_pagesize,float y_pagesize,boolean label_parameters)4333 boolean EditorWindow::printVisualProgramAsPS(const char *filename,
4334 float x_pagesize, float y_pagesize,
4335 boolean label_parameters)
4336 {
4337 FILE *fout = fopen(filename,"w");
4338 if (!fout) {
4339 ErrorMessage("Can't open file %s for writing",filename);
4340 return FALSE;
4341 }
4342
4343 //
4344 // Record the current page so that we can flip back there after the
4345 // print operation completes. (This because we're going to have to visit
4346 // each uninitialized page.)
4347 //
4348 int page = this->workSpace->getCurrentPage();
4349 WorkSpace *current_ews = this->workSpace;
4350 if (page) current_ews = this->workSpace->getElement(page);
4351
4352 //
4353 // Loop over the dictionary to get the pages to print. FIXME: this doesn't
4354 // print them in the order in which they appear on the screen. To do that,
4355 // you must build a new dictionary with the order_number as the key.
4356 //
4357 List* sorted_pages = this->pageSelector->getSortedPages();
4358 ASSERT(sorted_pages);
4359 ListIterator li(*sorted_pages);;
4360 EditorWorkSpace* ews;
4361 int pages_to_print = 0;
4362 int page_num = 1;
4363
4364 while ( (ews = (EditorWorkSpace*)li.getNext()) )
4365 if (ews->getPostscriptInclusion()) pages_to_print++;
4366
4367 if (pages_to_print == 0) {
4368 ErrorMessage (
4369 "You have removed every Visual Program page from the\n"
4370 "Postscript output. (See Edit/Page/Configure Page.)\n"
4371 "No output created."
4372 );
4373 return FALSE;
4374 }
4375
4376 boolean current_ews_changed = FALSE;
4377 li.setList(*sorted_pages);
4378 while ( (ews = (EditorWorkSpace*)li.getNext()) ) {
4379 if (ews->getPostscriptInclusion()) {
4380 if (ews->membersInitialized() == FALSE) {
4381 this->workSpace->showWorkSpace(ews);
4382 current_ews_changed = TRUE;
4383 }
4384 if (!this->printVisualProgramAsPS(fout, filename, x_pagesize,y_pagesize,
4385 label_parameters, ews, page_num, pages_to_print)) {
4386 fclose (fout);
4387 ErrorMessage("Error writing to file %s", filename);
4388 return FALSE;
4389 }
4390 page_num++;
4391 }
4392 }
4393 fclose (fout);
4394
4395 delete sorted_pages;
4396
4397 if (current_ews_changed)
4398 this->workSpace->showWorkSpace(current_ews);
4399
4400 return TRUE;
4401 }
4402
printVisualProgramAsPS(FILE * fout,const char * filename,float x_pagesize,float y_pagesize,boolean label_parameters,EditorWorkSpace * current_ews,int page_number,int of_howmany)4403 boolean EditorWindow::printVisualProgramAsPS(FILE* fout, const char* filename,
4404 float x_pagesize, float y_pagesize, boolean label_parameters,
4405 EditorWorkSpace* current_ews, int page_number, int of_howmany)
4406 {
4407 boolean landscape = FALSE;
4408 Node *n;
4409 float border_percent = .075;
4410 float printable_percent = 1.0 - 2*(border_percent);
4411 int xsize, ysize;
4412 time_t t;
4413 char *tod;
4414 int begx, begy;
4415 int endx, endy;
4416 List *arcs;
4417 StandIn *standIn;
4418 int i, icnt;
4419 int xpos, ypos, width, height;
4420 int xmin=1000000,xmax=0,ymin=1000000,ymax=0;
4421 Ark *a;
4422 // We allocate these ourselves because the hp gives the following message
4423 // sorry, not implemented: label in block with destructors (2048)
4424 ListIterator *iterator = new ListIterator, *iter2 = new ListIterator;
4425 Decorator *dec;
4426 VPEAnnotator *vpea;
4427 Symbol vpeas = theSymbolManager->registerSymbol(ClassVPEAnnotator);
4428 GroupRecord* grec;
4429 const char* group_name;
4430
4431
4432 xmin = 0; // Always use the upper left corner of the workspace as origin
4433 ymin = 0; // ditto
4434 FOR_EACH_NETWORK_NODE(this->network, n, (*iterator)) {
4435 standIn = n->getStandIn();
4436 if (!standIn)
4437 continue;
4438 #if WORKSPACE_PAGES
4439 if (standIn->getWorkSpace() != current_ews) continue;
4440 #endif
4441 standIn->getGeometry(&xpos, &ypos, &width, &height);
4442 xmax = MAX(xpos + width,xmax);
4443 ymax = MAX(ypos + height,ymax);
4444
4445 }
4446
4447 FOR_EACH_NETWORK_DECORATOR (this->network, dec, (*iterator)) {
4448 #if WORKSPACE_PAGES
4449 if (dec->getWorkSpace() != current_ews) continue;
4450 #endif
4451 dec->getXYPosition (&xpos, &ypos);
4452 dec->getXYSize (&width, &height);
4453 xmax = MAX(xpos + width, xmax);
4454 ymax = MAX(ypos + height,ymax);
4455 }
4456
4457 xsize = xmax - xmin;
4458 ysize = ymax - ymin;
4459
4460 if (xsize > ysize)
4461 landscape = TRUE;
4462
4463 /* Required for EPSF-3.0 */
4464 t = time(0);
4465 tod = ctime(&t);
4466 if (page_number == 1) {
4467 if (fprintf(fout, "%s", "%!PS-Adobe-3.0 EPSF-3.0\n") <= 0) goto error;
4468 if (fprintf(fout, "%%%%Creator: IBM/Data Explorer\n") <= 0) goto error;
4469 if (fprintf(fout, "%%%%CreationDate: %s", tod) <= 0) goto error;
4470 if (fprintf(fout, "%%%%Title: %s\n", filename) <= 0) goto error;
4471 if (fprintf(fout, "%%%%Pages: %d\n", of_howmany) <= 0) goto error;
4472
4473 /* Put a Bounding Box specification, required for EPSF-3.0 */
4474 begx = (int) ((x_pagesize * border_percent) * 72);
4475 begy = (int) ((y_pagesize * border_percent) * 72);
4476 endx = (int) ((x_pagesize * 72) - begx);
4477 endy = (int) ((y_pagesize * 72) - begy);
4478 if (fprintf(fout, "%%%%BoundingBox: %d %d %d %d\n",
4479 begx, begy, endx,endy) <= 0)
4480 goto error;
4481
4482 //
4483 // Begin the Setup section
4484 //
4485 if (fprintf(fout,"%%%%BeginSetup\n\n") < 0) goto error;
4486 if (fprintf(fout, "%% Build a temporary dictionary\n%d dict begin\n\n",
4487 25) < 0) goto error;
4488 if (!StandIn::PrintPostScriptSetup(fout)) goto error;
4489 if (fprintf(fout,"%%%%EndSetup\n\n") < 0) goto error;
4490 }
4491
4492
4493 //
4494 // Begin the Page Setup section
4495 //
4496 if (fprintf(fout,"\n%%%%Page: %d %d\n\n", page_number, page_number) <= 0) goto error;
4497
4498 if (fprintf(fout,"%%%%BeginPageSetup\n\n") < 0) goto error;
4499
4500
4501 if ((fprintf(fout,"%% Number of units/inch (don't change this one)\n"
4502 "/upi 72 def\n") <= 0) ||
4503 (fprintf(fout,"%% Size of output page in inches\n"
4504 "/pwidth %f def\n"
4505 "/pheight %f def\n",
4506 x_pagesize,y_pagesize) <= 0) ||
4507 (fprintf(fout,"%% Size of printable output page in inches\n"
4508 "/width %f pwidth mul def\n"
4509 "/height %f pheight mul def\n",
4510 printable_percent, printable_percent) <= 0) ||
4511 (fprintf(fout,"%% Extents of the used portion of the workspace\n"
4512 "/xmin %d def\n"
4513 "/xmax %d def\n"
4514 "/ymin %d def\n"
4515 "/ymax %d def\n",
4516 xmin, xmax,ymin,ymax) <= 0) ||
4517 (fprintf(fout,"%% Size of the used portion of the workspace\n"
4518 "/xsize xmax xmin sub def\n"
4519 "/ysize ymax ymin sub def\n") <= 0))
4520 goto error;
4521
4522
4523 if (landscape) {
4524 if ((fprintf(fout,"%% Rotate and translate into Landscape mode\n")
4525 <= 0) ||
4526 (fprintf(fout,"90 rotate\n0 pwidth neg upi mul translate\n\n")
4527 <= 0) ||
4528 (fprintf(fout,"%% Swap the width and height variables\n")
4529 <= 0) ||
4530 (fprintf(fout,"/tmp width def\n"
4531 "/width height def\n"
4532 "/height tmp def\n") <= 0) ||
4533 (fprintf(fout,"/tmp pwidth def\n"
4534 "/pwidth pheight def\n"
4535 "/pheight tmp def\n") <= 0))
4536 goto error;
4537 }
4538
4539 if (fprintf(fout,"%% Translate canvas inside page borders\n"
4540 "%f pwidth mul upi mul dup translate\n",
4541 border_percent ) <= 0)
4542 goto error;
4543
4544 if (fprintf(fout,"%% Scale canvas to the page with origin in upper left\n"
4545 "/max { %% Usage : a b max\n"
4546 " 2 dict begin\n"
4547 " /a 2 1 roll def\n"
4548 " /b 2 1 roll def\n"
4549 " a b gt\n"
4550 " { a } { b } ifelse\n"
4551 " end\n"
4552 "} def\n"
4553 "0 height upi mul translate\n"
4554 "xsize width div ysize height div max\n"
4555 "upi max\n" // Use at least 72 dpi
4556 "upi 2 1 roll div "
4557 "dup neg "
4558 "scale\n"
4559 "%% Now Translate to (xmin,ymin)\n"
4560 "xmin neg ymin neg translate\n" ) <= 0)
4561 goto error;
4562
4563
4564 if (fprintf(fout,"%%%%EndPageSetup\n\n") <= 0) goto error;
4565
4566
4567 //
4568 // And finally send the visual program.
4569 //
4570 FOR_EACH_NETWORK_NODE(this->network, n, (*iterator)) {
4571 standIn = n->getStandIn();
4572 if (!standIn)
4573 continue;
4574 #if WORKSPACE_PAGES
4575 if (standIn->getWorkSpace() != current_ews) continue;
4576 #endif
4577 standIn->printPostScriptPage(fout, label_parameters && (xsize < 1500));
4578 icnt = n->getInputCount();
4579 for (i=1 ; i<=icnt ; i++) {
4580 if (n->isInputConnected(i) &&
4581 n->isInputViewable(i) &&
4582 n->isInputVisible(i)) {
4583 arcs = (List*)n->getInputArks(i);
4584 ASSERT(arcs);
4585 iter2->setList(*arcs);
4586 while ( (a = (Ark*)iter2->getNext()) )
4587 a->getArkStandIn()->printAsPostScript(fout);
4588 }
4589 }
4590 }
4591
4592 FOR_EACH_NETWORK_DECORATOR (this->network, dec, (*iterator)) {
4593 #if WORKSPACE_PAGES
4594 if (dec->getWorkSpace() != current_ews) continue;
4595 #endif
4596 if (dec->isA(vpeas)) {
4597 vpea = (VPEAnnotator*)dec;
4598 vpea->printPostScriptPage(fout);
4599 }
4600 }
4601
4602 //
4603 // Oh, and one more thing. ...Page %s: %d of %d
4604 //
4605 char footer[128];
4606 grec = this->getGroupOfWorkSpace((EditorWorkSpace*)current_ews);
4607 group_name = (grec? grec->getName(): "<Untitled>");
4608 sprintf (footer, "%s - page %d of %d", group_name, page_number, of_howmany);
4609 if (fprintf (fout,
4610 "%% Reset translation, rotation, and scaling for making a page footer\n"
4611 "initmatrix\n"
4612 "/Helvetica-Bold findfont\n"
4613 "[ 10.0 0 0 10.0 0 0 ] makefont setfont\n"
4614 "%% (page width/2) - (string width/2) for centering the footer\n"
4615 "(%s) stringwidth pop 0.5 mul neg\n"
4616 "%f 0.5 mul upi mul add\n"
4617 "%% 0.5 inches up from the bottom of the page\n"
4618 "36 moveto\n"
4619 "(%s) show\n",
4620 footer, x_pagesize, footer) <=0) goto error;
4621
4622 //
4623 // Force the page out of the printer
4624 //
4625 if (fprintf(fout,"\nshowpage\n") <= 0) goto error;
4626
4627 if (page_number == of_howmany)
4628 if (fprintf(fout,"\nend\n") <= 0)
4629 goto error;
4630
4631 delete iterator;
4632 delete iter2;
4633 return TRUE;
4634
4635 error:
4636 delete iterator;
4637 delete iter2;
4638 return FALSE;
4639 }
4640
macroifySelectedNodes(const char * name,const char * cat,const char * desc,const char * fileName)4641 boolean EditorWindow::macroifySelectedNodes(const char *name,
4642 const char *cat,
4643 const char *desc,
4644 const char *fileName)
4645 {
4646 ListIterator li;
4647 Node *node;
4648
4649 //
4650 // Try and verify that the selected nodes are macrofiable.
4651 //
4652 if (!this->areSelectedNodesMacrofiable())
4653 return FALSE;
4654
4655 //
4656 // Get the set of selected nodes. If there are none, we're done.
4657 //
4658 List *l = this->makeSelectedNodeList();
4659 if (l == NULL || l->getSize() == 0) {
4660 if (l) delete l;
4661 return TRUE;
4662 }
4663
4664 //
4665 // Check to see if all these nodes are allowed in macros, get the
4666 // bounding box of the nodes on the vpe.
4667 //
4668 int x = 0, y = 0;
4669 node = (Node*)l->getElement(1);
4670 node->getVpePosition(&x, &y);
4671 int bboxXmin = x;
4672 int bboxYmin = y;
4673 int bboxYmax = y;
4674 for (li.setList(*l); (node = (Node*)li.getNext()); )
4675 {
4676
4677 node->getVpePosition(&x, &y);
4678 if(x < bboxXmin)
4679 bboxXmin = x;
4680 if(y < bboxYmin)
4681 bboxYmin = y;
4682 if(y > bboxYmax)
4683 bboxYmax = y;
4684 }
4685
4686 //
4687 // Create and setup the new network
4688 //
4689 Network *net = theDXApplication->newNetwork();
4690
4691 net->setName(name? name: "NewMacro");
4692 net->setCategory(cat? cat: "Macros");
4693 net->setDescription(desc? desc: "new macro");
4694
4695 if (!net->makeMacro(TRUE))
4696 {
4697 delete net;
4698 delete l;
4699 return FALSE;
4700 }
4701
4702 MacroDefinition *nd = net->getDefinition();
4703 nd->setNetwork(net);
4704 theDXApplication->macroList.appendElement(net);
4705
4706 theNodeDefinitionDictionary->replaceDefinition(nd->getNameString(), nd);
4707 ToolSelector::AddTool(nd->getCategorySymbol(),
4708 nd->getNameSymbol(),
4709 (void *)nd);
4710 ToolSelector::UpdateCategoryListWidget();
4711
4712 //
4713 // For each arc, if the arc crosses the line between selected and
4714 // unselected nodes, delete it and set up a macro input.
4715 // if it is only in the new macro, delete and recreate the arc.
4716 //
4717 struct connection {
4718 Node *n;
4719 int param;
4720 Node *pn;
4721 };
4722 List newInputs;
4723 List newOutputs;
4724 connection *con;
4725 for (li.setList(*l); (node = (Node*)li.getNext()); )
4726 {
4727 List *orig;
4728 int i;
4729 for (i = 1; i <= node->getInputCount(); ++i)
4730 {
4731 orig = (List*)node->getInputArks(i);
4732 List *inputs = orig->dup();
4733 ListIterator li(*inputs);
4734 Ark *a;
4735 while ( (a = (Ark*)li.getNext()) )
4736 {
4737 int param;
4738 Node *source = a->getSourceNode(param);
4739 StandIn *si = source->getStandIn();
4740 source->deleteArk(a);
4741 si->deleteArk(a);
4742
4743 if (!si->isSelected()) {
4744 ListIterator connections(newInputs);
4745 while ( (con = (connection *)connections.getNext()) ) {
4746 if (source == con->n && param == con->param)
4747 break;
4748 }
4749 if (con == NULL) {
4750 con = new connection;
4751 con->n = source;
4752 con->param = param;
4753
4754 MacroParameterDefinition *inputDef =
4755 (MacroParameterDefinition*)
4756 theNodeDefinitionDictionary->
4757 findDefinition("Input");
4758 con->pn = inputDef->createNewNode(net);
4759 net->addNode(con->pn);
4760 newInputs.appendElement(con);
4761 }
4762 new Ark(con->pn, 1, node, i);
4763 }
4764 else {
4765 new Ark(source, param, node, i);
4766 }
4767 }
4768 delete inputs;
4769 }
4770
4771 for (i = 1; i <= node->getOutputCount(); ++i)
4772 {
4773 orig = (List*)node->getOutputArks(i);
4774 List *outputs = orig->dup();
4775 ListIterator li(*outputs);
4776 Ark *a;
4777 while ( (a = (Ark*)li.getNext()) )
4778 {
4779 int param;
4780 Node *dest = a->getDestinationNode(param);
4781 StandIn *si = dest->getStandIn();
4782 dest->deleteArk(a);
4783 si->deleteArk(a);
4784
4785 if (!si->isSelected()) {
4786 ListIterator connections(newOutputs);
4787 while ( (con = (connection*)connections.getNext()) ) {
4788 if (dest == con->n && param == con->param)
4789 break;
4790 }
4791 if (con == NULL) {
4792 con = new connection;
4793 con->n = dest;
4794 con->param = param;
4795
4796 MacroParameterDefinition *outputDef =
4797 (MacroParameterDefinition*)
4798 theNodeDefinitionDictionary->
4799 findDefinition("Output");
4800 con->pn = outputDef->createNewNode(net);
4801 con->pn->setVpePosition(0,bboxYmax-bboxYmin+2*80);
4802 net->addNode(con->pn);
4803 newOutputs.appendElement(con);
4804 }
4805 new Ark(node, i, con->pn, 1);
4806 }
4807 else {
4808 new Ark(node, i, dest, param);
4809 }
4810 }
4811 delete outputs;
4812 }
4813 }
4814
4815 //
4816 // Switch the nodes to the newly created network.
4817 //
4818 if (!net->mergeNetworks (this->network, NULL, FALSE)) {
4819 delete l;
4820 return FALSE;
4821 }
4822
4823 XmUpdateDisplay(this->getRootWidget());
4824
4825 //
4826 // Move the nodes to the upper right hand corner after switching them
4827 // to the new net. This is the last use of "l".
4828 //
4829 for (li.setList(*l); (node = (Node*)li.getNext()); )
4830 {
4831 node->getVpePosition(&x,&y);
4832 node->setVpePosition(x-bboxXmin, y-bboxYmin+80);
4833 }
4834 delete l;
4835
4836 net->sortNetwork();
4837
4838 node = nd->createNewNode(this->network);
4839 if (!node)
4840 {
4841 delete net;
4842 return FALSE;
4843 }
4844 node->setVpePosition(bboxXmin, bboxYmin);
4845
4846 this->network->addNode(node);
4847
4848
4849 int i;
4850 for (i = 1; (con = (connection*)newInputs.getElement(1)); ++i) {
4851 node->getStandIn()->addArk(this, new Ark(con->n, con->param, node, i));
4852 delete con;
4853 newInputs.deleteElement(1);
4854 }
4855 newInputs.clear();
4856 for (i = 1; (con = (connection*)newOutputs.getElement(1)); ++i) {
4857 node->getStandIn()->addArk(this, new Ark(node, i, con->n, con->param));
4858 delete con;
4859 newOutputs.deleteElement(1);
4860 }
4861 newOutputs.clear();
4862
4863 if (fileName)
4864 net->saveNetwork(fileName, TRUE);
4865
4866 #ifndef FORGET_GETSET
4867 if ((EditorWindow::GetSetDialog) && (EditorWindow::GetSetDialog->isManaged()))
4868 EditorWindow::GetSetDialog->update();
4869 #endif
4870
4871 return TRUE;
4872 }
4873
postInsertNetworkDialog()4874 void EditorWindow::postInsertNetworkDialog()
4875 {
4876 if (this->insertNetworkDialog == NULL)
4877 this->insertNetworkDialog = new InsertNetworkDialog(this->getRootWidget());
4878 this->insertNetworkDialog->post();
4879 }
postCreateMacroDialog()4880 void EditorWindow::postCreateMacroDialog()
4881 {
4882 if (this->createMacroDialog == NULL)
4883 this->createMacroDialog = new CreateMacroDialog(
4884 this->getRootWidget(),
4885 this);
4886 this->createMacroDialog->post();
4887 }
optimizeNodeOutputCacheability()4888 void EditorWindow::optimizeNodeOutputCacheability()
4889 {
4890 this->network->optimizeNodeOutputCacheability();
4891 }
4892 //
4893 // Search all nodes and select those with any outputs that match the
4894 // give cachability.
4895 //
selectNodesWithOutputCacheability(Cacheability c)4896 void EditorWindow::selectNodesWithOutputCacheability(Cacheability c)
4897 {
4898 Node *node;
4899
4900 //
4901 // Scan the tools and select them if any of their outputs have the
4902 // given cachability.
4903 //
4904 ListIterator iterator;
4905 FOR_EACH_NETWORK_NODE(this->network, node, iterator) {
4906 int i, cnt = node->getOutputCount();
4907 boolean select = FALSE;
4908 for (i=1 ; i<=cnt && !select ; i++) {
4909 if (node->getOutputCacheability(i) == c)
4910 select = TRUE;
4911 }
4912 this->selectNode(node, select, FALSE);
4913 }
4914
4915 }
4916 //
4917 // Set the cacheability of all outputs of the selected tools to one of
4918 // OutputFullyCached, OutputNotCached or OutputCacheOnce.
4919 // A warning is issued on those nodes that do not have writeable cacheability.
4920 //
setSelectedNodesOutputCacheability(Cacheability c)4921 void EditorWindow::setSelectedNodesOutputCacheability(Cacheability c)
4922 {
4923 #define MAX_IGNORES 256
4924 int i;
4925 Dictionary ignored;
4926 Node *node;
4927 List *snlist = this->makeSelectedNodeList();
4928
4929 ASSERT((c == OutputFullyCached) || (c == OutputNotCached) ||
4930 (c == OutputCacheOnce));
4931
4932 if (NOT snlist)
4933 return;
4934
4935 //
4936 // Scan the list of selected tools and change their outputs' cacheability
4937 // if it is writeable.
4938 //
4939 ListIterator li(*snlist);
4940 while ( (node = (Node*)li.getNext()) ) {
4941 int i, cnt = node->getOutputCount();
4942 for (i=1 ; i<=cnt ; i++) {
4943 if (node->isOutputCacheabilityWriteable(i)) {
4944 node->setOutputCacheability(i,c);
4945 } else {
4946 const char *name = node->getNameString();
4947 if (!ignored.findDefinition(name))
4948 ignored.addDefinition(name,name);
4949 }
4950 }
4951 }
4952
4953 //
4954 // Notify the user about any modules that were skipped above
4955 //
4956 int num_ignored = ignored.getSize();
4957 if (num_ignored > 0) {
4958 char *name, *p, *tools = new char[num_ignored * 64];
4959 tools[0] = '\0';
4960 p = tools;
4961 DictionaryIterator di(ignored);
4962 for (i=0 ; (name = (char*)di.getNextDefinition()); i++, p+=STRLEN(p)) {
4963 sprintf(p,"%s ",name);
4964 if ((i != 0) && ((i & 3) == 0))
4965 strcat(p,"\n"); // 4 tool names per line of text.
4966 }
4967 WarningMessage("One or more of the outputs of the following tools has "
4968 "a read-only cacheability setting\n"
4969 "(operation ignored for those outputs):\n\n%s", tools);
4970 delete tools;
4971 }
4972 delete snlist;
4973 }
postSaveAsCCodeDialog()4974 void EditorWindow::postSaveAsCCodeDialog()
4975 {
4976 #ifdef DXUI_DEVKIT
4977 if (NOT this->saveAsCCodeDialog)
4978 this->saveAsCCodeDialog = new SaveAsCCodeDialog(
4979 this->getRootWidget(),this->getNetwork());
4980 this->saveAsCCodeDialog->post();
4981 #endif // DXUI_DEVKIT
4982 }
4983
4984 //
4985 // This is a helper method for this->areSelectedNodesMacrofiable().
4986 // It recursively descends the connections from the given node to determine
4987 // if it connected to a selected node. If ignoreDirectConnect is TRUE,
4988 // then we do not care about selected nodes that are directly connected
4989 // to selected nodes.
4990 // Returns TRUE if there is a downstream selected node, otherwise FALSE.
4991 //
isSelectedNodeDownstream(Node * srcNode,boolean ignoreDirectConnect)4992 boolean EditorWindow::isSelectedNodeDownstream(Node *srcNode,
4993 boolean ignoreDirectConnect)
4994 {
4995 int i, j;
4996 StandIn *srcStandIn = srcNode->getStandIn();
4997
4998 if (!srcStandIn)
4999 return FALSE;
5000
5001 boolean srcSelected = srcStandIn->isSelected();
5002
5003 ASSERT(!srcSelected || ignoreDirectConnect);
5004
5005 int numParam = srcNode->getOutputCount();
5006
5007 for (i = 1; i <= numParam; ++i)
5008 {
5009 if (srcNode->isOutputConnected(i))
5010 {
5011 Ark *a;
5012 List *arcs = (List *)srcNode->getOutputArks(i);
5013 for (j = 1; (a = (Ark*)arcs->getElement(j)); ++j)
5014 {
5015 int paramInd;
5016 Node *destNode = a->getDestinationNode(paramInd);
5017 if (destNode->isMarked())
5018 continue;
5019 StandIn *destStandIn = destNode->getStandIn();
5020 if (!destStandIn)
5021 continue;
5022 boolean destSelected = destStandIn->isSelected();
5023 if (srcSelected && !destSelected) {
5024 if (this->isSelectedNodeDownstream(destNode,FALSE))
5025 return TRUE;
5026 } else if (srcSelected && destSelected) {
5027 if (!ignoreDirectConnect)
5028 return TRUE;
5029 } else if (!srcSelected && destSelected) {
5030 return TRUE;
5031 } else { // !srcSelected && !destSelected
5032 if (this->isSelectedNodeDownstream(destNode,FALSE))
5033 return TRUE;
5034 }
5035 if (!destSelected)
5036 destNode->setMarked();
5037 }
5038 }
5039 }
5040
5041 return FALSE;
5042 }
5043 //
5044 // Determine if the currently selected set of nodes is macrofiable. In
5045 // particular, we check for selections that would result in an output
5046 // being connected to on input of the newly created macro. To do this
5047 // we look at each selected node and determine if its immediate downstream
5048 // unselected nodes are connected (possibly through intermediate nodes)
5049 // to another of the selected nodes.
5050 // Returns TRUE if macrofiable, else returns FALSE and issues and error
5051 // message.
5052 //
areSelectedNodesMacrofiable()5053 boolean EditorWindow::areSelectedNodesMacrofiable()
5054 {
5055
5056 int i;
5057 Network *network = this->network;
5058 int numNodes = network->nodeList.getSize();
5059 List tmpNodeList;
5060 ListIterator iterator;
5061 Node *n;
5062 boolean saw_tmtr = FALSE, saw_rcvr = FALSE;
5063 List *tmtrs = NULL, *rcvrs = NULL;
5064
5065 if (numNodes == 0)
5066 return TRUE;
5067
5068 iterator.setList(network->nodeList);
5069 for (i=0 ; (n = (Node*)iterator.getNext()) ; i++)
5070 n->clearMarked();
5071
5072 //
5073 // The HP gives the following message if I try to use a goto
5074 // CC: "EditorWindow.C", line 3510: sorry, not implemented: label in
5075 // block with destructors (2048)
5076 //
5077 #define RETURN_FALSE if (tmtrs) delete tmtrs; \
5078 if (rcvrs) delete rcvrs; \
5079 return FALSE;
5080
5081 iterator.setList(network->nodeList);
5082 while ( (n = (Node*)iterator.getNext()) ) {
5083 StandIn *si = n->getStandIn();
5084 if (si && si->isSelected()) {
5085 if (this->isSelectedNodeDownstream(n,TRUE)) {
5086 ErrorMessage(
5087 "The currently selected tools can not be macrofied because the"
5088 "\nresulting macro would have an output connected to an input."
5089 "\nThis is due to the fact that a data path that leaves the "
5090 "\nselected tools later reenters the selected tools.");
5091 RETURN_FALSE;
5092 } else if (!n->isAllowedInMacro()) {
5093 ErrorMessage("Tool %s is not allowed in a macro",
5094 n->getNameString());
5095 RETURN_FALSE;
5096 } else if (n->isA(ClassMacroParameterNode)) {
5097 ErrorMessage(
5098 "Tool %s is not allowed in an automatically created macro",
5099 n->getNameString());
5100 RETURN_FALSE;
5101 } else if (n->isA(ClassTransmitterNode)) {
5102 if (!saw_tmtr) {
5103 rcvrs = network->makeClassifiedNodeList(ClassReceiverNode);
5104 saw_tmtr = TRUE;
5105 }
5106 if (rcvrs) {
5107 ListIterator iter(*rcvrs);
5108 const char *tlabel = n->getLabelString();
5109 Node *r;
5110 while ( (r = (Node*)iter.getNext()) ) {
5111 StandIn *rsi = r->getStandIn();
5112 if (rsi && !rsi->isSelected() &&
5113 EqualString(r->getLabelString(),tlabel)) {
5114 ErrorMessage(
5115 "The currently selected tools can not be macrofied "
5116 "because the selected\nTransmitter %s has a "
5117 "corresponding Receiver that is not selected.\n",
5118 tlabel);
5119 RETURN_FALSE;
5120 }
5121 }
5122 }
5123 } else if (n->isA(ClassReceiverNode)) {
5124 if (!saw_rcvr) {
5125 tmtrs =
5126 network->makeClassifiedNodeList(ClassTransmitterNode);
5127 saw_rcvr = TRUE;
5128 }
5129 if (tmtrs) {
5130 ListIterator iter(*tmtrs);
5131 const char *rlabel = n->getLabelString();
5132 Node *t;
5133 while ( (t = (Node*)iter.getNext()) ) {
5134 StandIn *tsi = t->getStandIn();
5135 if (tsi && !tsi->isSelected() &&
5136 EqualString(t->getLabelString(),rlabel)) {
5137 ErrorMessage(
5138 "The currently selected tools can not be macrofied "
5139 "because the selected\nReceiver %s has a "
5140 "corresponding Transmitter that is not selected.\n",
5141 rlabel);
5142 RETURN_FALSE;
5143 }
5144 }
5145 }
5146 }
5147 }
5148 }
5149
5150 if (tmtrs) delete tmtrs;
5151 if (rcvrs) delete rcvrs;
5152 return TRUE;
5153
5154 }
5155
5156
5157 #ifndef FORGET_GETSET
5158 //
5159 // convert selected nodes (guaranteed to be either Get or Set) to
5160 // Global
5161 //
5162 void
ConvertToGlobal(boolean global)5163 EditorWindow::ConvertToGlobal(boolean global)
5164 {
5165 EditorWindow* e = EditorWindow::GetSetDialog->getActiveEditor();
5166 ASSERT(e);
5167 e->convertToGlobal(global);
5168 }
5169
5170 void
convertToGlobal(boolean global)5171 EditorWindow::convertToGlobal(boolean global)
5172 {
5173 List *glnlist = this->makeSelectedNodeList();
5174
5175 // The command can't be active if there is not selected node in the vpe.
5176 ASSERT(glnlist);
5177 ListIterator it(*glnlist);
5178 GlobalLocalNode *gln;
5179
5180 while ( (gln = (GlobalLocalNode*)it.getNext()) ) {
5181 ASSERT (((Node*)gln)->isA(ClassGlobalLocalNode));
5182 // Both of the following return FALSE if the node has never been set
5183 // Taken together, these 3 ASSERTS mean that everything in the list
5184 // is either a Get or a Set.
5185 //ASSERT (!gln->isGlobalNode());
5186 //ASSERT (!gln->isLocalNode());
5187
5188 if (global) gln->setAsGlobalNode();
5189 else gln->setAsLocalNode();
5190 }
5191 delete glnlist;
5192
5193 this->setCommandActivation();
5194 if (EditorWindow::GetSetDialog)
5195 EditorWindow::GetSetDialog->setCommandActivation();
5196
5197 }
5198
5199 void
ConvertToLocal()5200 EditorWindow::ConvertToLocal()
5201 {
5202 EditorWindow::ConvertToGlobal(FALSE);
5203 }
5204
5205 #endif
5206
5207
5208 #if WORKSPACE_PAGES
5209 //
5210 // Turn the selected nodes into a page.
5211 // Any arc of a selected node must go to a node which is also selected.
5212 // The Edit/Select/Selected Connected command works well for selecting pagifiable nodes.
5213 //
5214 boolean
pagifySelectedNodes(boolean include_selected_nodes)5215 EditorWindow::pagifySelectedNodes(boolean include_selected_nodes)
5216 {
5217 char page_name[64];
5218
5219 //
5220 // See if the selected nodes are pagifiable.
5221 // Creating the group automatically includes selected nodes, so if we don't
5222 // want them included, deselect them.
5223 //
5224 List *l = NUL(List*);
5225 List *dl = NUL(List*);
5226 boolean pagifiable = this->areSelectedNodesPagifiable(include_selected_nodes);
5227 if ((!pagifiable) && (include_selected_nodes)) {
5228 return FALSE;
5229 } else if ((pagifiable) && (include_selected_nodes)) {
5230 l = this->makeSelectedNodeList();
5231 dl = this->makeSelectedDecoratorList();
5232 } else {
5233 this->deselectAllNodes();
5234 }
5235
5236 //
5237 // Find an unused name for a new page.
5238 //
5239 boolean page_name_in_use = TRUE;
5240 int next_page_no = 1;
5241 while (page_name_in_use) {
5242 sprintf (page_name, "Untitled_%d", next_page_no++);
5243 const void* def_found = this->pageSelector->findDefinition (page_name);
5244 if (def_found == NUL(void*))
5245 page_name_in_use = FALSE;
5246 }
5247
5248 //
5249 // Create a new page group in the network.
5250 // Creating the new group also automatically marks selected nodes as belonging.
5251 //
5252 GroupManager *page_mgr = (GroupManager*)
5253 this->network->getGroupManagers()->findDefinition(PAGE_GROUP);
5254 ASSERT(page_mgr->createGroup (page_name, this->network));
5255
5256 //
5257 // Make the new WorkSpace page.
5258 //
5259 EditorWorkSpace *page = (EditorWorkSpace*)this->workSpace->addPage();
5260 ASSERT (this->pageSelector->addDefinition (page_name, page));
5261 PageGroupRecord *grec = (PageGroupRecord*)page_mgr->getGroup (page_name);
5262 grec->setComponents (NUL(UIComponent*), page);
5263
5264 //
5265 // Move the standins and decorators out their old page
5266 //
5267 if ((include_selected_nodes) && ((l) || (dl))) {
5268
5269 //
5270 // prepare to turn off/on line drawing if moving standins
5271 //
5272 EditorWorkSpace *selectedWS = NUL(EditorWorkSpace*);
5273 if ((l) && (l->getSize())) {
5274 Node* n = (Node*)l->getElement(1);
5275 StandIn* si = (StandIn*)n->getStandIn();
5276 selectedWS = (EditorWorkSpace*)si->getWorkSpace();
5277 } else if ((dl) && (dl->getSize())) {
5278 Decorator* dec = (Decorator*)dl->getElement(1);
5279 selectedWS = (EditorWorkSpace*)dec->getWorkSpace();
5280 }
5281
5282 if (selectedWS) selectedWS->beginManyPlacements();
5283 this->moveDecorators (page, dl, 20, 20, l);
5284 this->moveStandIns (page, l, 20, 20, dl);
5285 if (selectedWS) selectedWS->endManyPlacements();
5286 }
5287
5288 if (l) delete l;
5289 if (dl) delete dl;
5290 return TRUE;
5291 }
5292 #endif
5293
5294
5295
5296 #if WORKSPACE_PAGES
5297 //
5298 // Delete the page and everything inside the page and the page group.
5299 // If the group_name passed in is NULL, then delete the current page.
5300 //
5301 boolean
deletePage(const char * to_delete)5302 EditorWindow::deletePage(const char* to_delete)
5303 {
5304 //
5305 // Find the workspace we're deleting. We also need to know if we're deleting
5306 // the current workspace. If current is being deleted, then we'll have to
5307 // present some other workspace after deletion.
5308 //
5309 EditorWorkSpace* ews = NUL(EditorWorkSpace*);
5310 if (to_delete) ews = (EditorWorkSpace*)this->pageSelector->findDefinition (to_delete);
5311 int page = this->workSpace->getCurrentPage();
5312 EditorWorkSpace* current_ews = this->workSpace;
5313 if (page) current_ews = (EditorWorkSpace*)this->workSpace->getElement(page);
5314 if (ews == NUL(EditorWorkSpace*)) ews = current_ews;
5315 boolean deleted_was_current = (ews == current_ews);
5316
5317 //
5318 // Find all the guys whose group name is the same as the group name of
5319 // the workspace we're deleting. Somewhat roundabout, but it works for
5320 // both situations... a) deleting a named page, b) deleting the current page.
5321 //
5322 boolean first = TRUE;
5323 const char *group_name = NUL(char*);
5324 Node *node;
5325 ListIterator iter;
5326 List nodeList;
5327 List decorList;
5328 Decorator *decor;
5329 nodeList.clear();
5330 decorList.clear();
5331 FOR_EACH_NETWORK_NODE(this->network, node, iter) {
5332 StandIn *si = node->getStandIn();
5333 if (!si) continue;
5334 WorkSpace* nws = si->getWorkSpace();
5335 if (nws == ews) {
5336 nodeList.appendElement((void*)node);
5337 if (first) {
5338 group_name = node->getGroupName(theSymbolManager->getSymbol(PAGE_GROUP));
5339 first = FALSE;
5340 }
5341 }
5342 }
5343 FOR_EACH_NETWORK_DECORATOR(this->network, decor, iter) {
5344 WorkSpace* nws = decor->getWorkSpace();
5345 if (nws == ews) {
5346 decorList.appendElement((void*)decor);
5347 }
5348 }
5349
5350 //
5351 // Now all the nodes/decorators are gathered up. Delete them.
5352 //
5353 this->deleteNodes(&nodeList);
5354 nodeList.clear();
5355 ListIterator it(decorList);
5356 while ( (decor = (Decorator*)it.getNext()) ) {
5357 this->network->decoratorList.removeElement((void*)decor);
5358 delete decor;
5359 }
5360
5361 if ((to_delete) && (group_name)) {
5362 ASSERT(EqualString(to_delete, group_name));
5363 }
5364
5365 //
5366 // If there was a node in the group then we'll have the name otherwise
5367 // we don't know the name and we'll have to scan the Dictionary
5368 //
5369 GroupManager *page_mgr = (GroupManager*)
5370 this->network->getGroupManagers()->findDefinition (PAGE_GROUP);
5371 if (to_delete) {
5372 this->pageSelector->removeDefinition ((const char*)to_delete);
5373 page_mgr->removeGroup(to_delete, this->network);
5374 } else if (group_name) {
5375 this->pageSelector->removeDefinition ((const char*)group_name);
5376 page_mgr->removeGroup(group_name, this->network);
5377 } else {
5378 boolean found = FALSE;
5379 int i, pcnt = this->pageSelector->getSize();
5380 for (i=1; i<=pcnt; i++) {
5381 EditorWorkSpace *def = (EditorWorkSpace*)
5382 this->pageSelector->getDefinition(i);
5383 if (def == ews) {
5384 group_name = this->pageSelector->getStringKey(i);
5385 this->pageSelector->removeDefinition ((const char*)group_name);
5386 found = TRUE;
5387 break;
5388 }
5389 }
5390 ASSERT(found);
5391 page_mgr->removeGroup(group_name, this->network);
5392 }
5393
5394 //
5395 // If it was really a subpage and not the root page.
5396 //
5397 if (ews != this->workSpace) {
5398 WorkSpaceInfo* info = ews->getInfo();
5399 delete ews;
5400 delete info;
5401 }
5402
5403 //
5404 // We've deleted what was the visible page. Now we must find a different page
5405 // to present to the user. Walk the list of pages looking for one which has
5406 // had standins created. (We don't want to accidently present a mamoth page
5407 // which will take a long time to fill.) If none is found with standins, then
5408 // try to put up one which contains fewest members. Else just put up page 0.
5409 // Putting up page 0 might require adding "Untitled" to the pageSelector.
5410 //
5411 if (deleted_was_current) {
5412 boolean found = FALSE;
5413 DictionaryIterator di(*this->pageSelector);
5414 int member_count = 9999999;
5415 EditorWorkSpace* contains_few_members = NUL(EditorWorkSpace*);
5416 while ( (ews = (EditorWorkSpace*)di.getNextDefinition()) ) {
5417 if (ews->membersInitialized()) {
5418 found = TRUE;
5419 this->pageSelector->selectPage(ews);
5420 break;
5421 } else {
5422 int current_count = this->getPageMemberCount(ews);
5423 if ((current_count > 0) && (current_count < member_count)) {
5424 member_count = current_count;
5425 contains_few_members = (EditorWorkSpace*)ews;
5426 }
5427 /*if (ews == this->workSpace)
5428 contains_root = TRUE;*/
5429 }
5430 }
5431 if (!found) {
5432 if (contains_few_members) {
5433 this->pageSelector->selectPage(contains_few_members);
5434 } else if (this->pageSelector->getSize()) {
5435 EditorWorkSpace* ws = (EditorWorkSpace*)
5436 this->pageSelector->getDefinition(1);
5437 ASSERT(ws);
5438 this->pageSelector->selectPage(ws);
5439 } else {
5440 this->pageSelector->addDefinition ("Untitled", this->workSpace);
5441 this->pageSelector->selectPage(this->workSpace);
5442 }
5443 }
5444 }
5445
5446 return TRUE;
5447 }
5448 #endif
5449
5450
5451 EditorWorkSpace *
getNodesBBox(int * minx,int * miny,int * maxx,int * maxy,List * l,List * dl)5452 EditorWindow::getNodesBBox(int *minx, int *miny, int *maxx, int *maxy, List *l, List *dl)
5453 {
5454 //
5455 // get the bounding box of the nodes on the vpe.
5456 //
5457 int x = 0, y = 0;
5458 int bboxXmin = 0, bboxYmin = 0;
5459 int bboxXmax = 1, bboxYmax = 1;
5460 ListIterator li;
5461 int width, height;
5462 EditorWorkSpace *selectedWorkSpace = NULL;
5463 boolean first = TRUE;
5464
5465 if (l) {
5466 li.setList(*l);
5467 Node *node;
5468 while ( (node = (Node*)li.getNext()) ) {
5469 node->getVpePosition(&x, &y);
5470 if (first) {
5471 bboxXmin = x;
5472 bboxYmin = y;
5473 first = FALSE;
5474 }
5475 StandIn *si = node->getStandIn();
5476
5477 if (si) {
5478 si->getXYSize (&width, &height);
5479 if (!selectedWorkSpace)
5480 selectedWorkSpace = (EditorWorkSpace*)si->getWorkSpace();
5481 ASSERT (selectedWorkSpace == (EditorWorkSpace*)si->getWorkSpace());
5482 } else {
5483 width = height = 0;
5484 }
5485
5486 if(x < bboxXmin)
5487 bboxXmin = x;
5488
5489 if((x+width) > bboxXmax)
5490 bboxXmax = x + width;
5491
5492 if(y < bboxYmin)
5493 bboxYmin = y;
5494
5495 if((y+height) > bboxYmax)
5496 bboxYmax = y + height;
5497 }
5498 }
5499
5500 if (dl) {
5501 li.setList(*dl);
5502 Decorator *dec = NULL;
5503 while ( (dec = (Decorator*)li.getNext()) ) {
5504 dec->getXYPosition (&x, &y);
5505 if (first) {
5506 bboxXmin = x;
5507 bboxYmin = y;
5508 first = FALSE;
5509 }
5510 dec->getXYSize (&width, &height);
5511
5512 if(x < bboxXmin)
5513 bboxXmin = x;
5514
5515 if((x+width) > bboxXmax)
5516 bboxXmax = x + width;
5517
5518 if(y < bboxYmin)
5519 bboxYmin = y;
5520
5521 if((y+height) > bboxYmax)
5522 bboxYmax = y + height;
5523 }
5524 }
5525
5526 *minx = bboxXmin;
5527 *miny = bboxYmin;
5528 *maxx = bboxXmax;
5529 *maxy = bboxYmax;
5530 return selectedWorkSpace;
5531 }
5532
5533 #if WORKSPACE_PAGES
5534
5535 //
5536 // Destroy all standins in the list
5537 //
destroyStandIns(List * selectedNodes)5538 void EditorWindow::destroyStandIns(List* selectedNodes)
5539 {
5540 boolean error_node = FALSE;
5541 int i;
5542 ListIterator li(*selectedNodes);
5543 Node *node;
5544
5545 while ( (node = (Node*)li.getNext()) ) {
5546 //
5547 // Destroy the input arcs
5548 //
5549 int count = node->getInputCount();
5550 for (i=1; i<=count; i++) {
5551 Ark *a;
5552 List *orig = (List*)node->getInputArks(i);
5553 List *conns = orig->dup();
5554 ListIterator ai(*conns);
5555 while ( (a = (Ark*)ai.getNext()) ) {
5556 ArkStandIn *asi = a->getArkStandIn();
5557 a->setArkStandIn(NULL);
5558 delete asi;
5559 }
5560 delete conns;
5561 }
5562
5563 //
5564 // Destroy the output arcs
5565 //
5566 count = node->getOutputCount();
5567 for (i=1; i<=count; i++) {
5568 Ark *a;
5569 List *orig = (List*)node->getOutputArks(i);
5570 List *conns = orig->dup();
5571 ListIterator ai(*conns);
5572 while ( (a = (Ark*)ai.getNext()) ) {
5573 ArkStandIn *asi = a->getArkStandIn();
5574 a->setArkStandIn(NULL);
5575 delete asi;
5576 }
5577 delete conns;
5578 }
5579
5580
5581 //
5582 // Destroy the existing StandIn for the node, making sure to remove it
5583 // from the error list if necessary.
5584 //
5585 StandIn *si = node->getStandIn();
5586 if (si) {
5587 si->unmanage();
5588 if (this->errored_standins)
5589 error_node|= this->errored_standins->removeElement((void*)si);
5590 delete si;
5591 }
5592 }
5593
5594 if (error_node)
5595 this->resetErrorList(FALSE);
5596 }
5597
5598 void
moveStandIns(EditorWorkSpace * page,List * selectedNodes,int xoff,int yoff,List * dl)5599 EditorWindow::moveStandIns(EditorWorkSpace *page, List* selectedNodes, int xoff, int yoff, List *dl)
5600 {
5601 int minx, miny, maxx, maxy;
5602
5603 if (!selectedNodes) return ;
5604
5605 this->getNodesBBox (&minx, &miny, &maxx, &maxy, selectedNodes, dl);
5606
5607 this->destroyStandIns(selectedNodes);
5608
5609 Node *node;
5610 ListIterator li(*selectedNodes);
5611 while ( (node = (Node*)li.getNext()) ) {
5612 int x,y;
5613 //
5614 // Record bbox relative position, incoming, outgoing arcs
5615 //
5616 node->getVpePosition(&x, &y);
5617
5618 //
5619 // Make a new StandIn using the saved position info.
5620 //
5621 node->setVpePosition (xoff + x - minx, yoff + y - miny);
5622 }
5623 page->setMembersInitialized(FALSE);
5624
5625 }
5626 #endif
5627
5628
5629 #if WORKSPACE_PAGES
5630 void
moveDecorators(EditorWorkSpace * page,List * seldec,int xoff,int yoff,List * nl)5631 EditorWindow::moveDecorators(EditorWorkSpace *page, List* seldec, int xoff, int yoff, List*nl)
5632 {
5633 int minx, miny, maxx, maxy;
5634 Decorator *dec;
5635 int x,y;
5636
5637 if (!seldec) return ;
5638
5639 this->getNodesBBox (&minx, &miny, &maxx, &maxy, nl, seldec);
5640
5641 Widget page_w = page->getRootWidget();
5642 Window page_wnd = (page_w?XtWindow(page_w):NUL(Window));
5643
5644 ListIterator it(*seldec);
5645 while ( (dec = (Decorator*)it.getNext()) ) {
5646 dec->getXYPosition (&x, &y);
5647 dec->unmanage();
5648 dec->uncreateDecorator();
5649 dec->setXYPosition (xoff + x - minx, yoff + y - miny);
5650 if ((page_w) && (page_wnd))
5651 dec->manage(page);
5652 else
5653 page->setMembersInitialized(FALSE);
5654 }
5655 }
5656
5657 //
5658 // If the standin is selected, then any arcs must go only to a selected standin
5659 // and not to an unselected standin.
5660 //
5661 // This is where nodes might automatically be replaced with Transmitter/Reciever
5662 // pairs.
5663 //
5664 boolean
areSelectedNodesPagifiable(boolean report)5665 EditorWindow::areSelectedNodesPagifiable(boolean report)
5666 {
5667 boolean retVal = TRUE;
5668 EditorWorkSpace *ws = NULL;
5669
5670
5671 List *l = this->makeSelectedNodeList();
5672 if ((!l) || (!l->getSize())) {
5673 if (l) delete l;
5674 return TRUE;
5675 }
5676
5677 ListIterator snl(*l);
5678 Node *node;
5679 while ((retVal) && (node = (Node*)snl.getNext())) {
5680 int i,count = node->getInputCount();
5681 List *conns = NULL;
5682
5683 for (i=1; ((retVal) && (i<=count)); i++) {
5684 Ark *a;
5685 List *orig = (List*)node->getInputArks(i);
5686 conns = orig->dup();
5687 ListIterator ai(*conns);
5688 while ( (a = (Ark*)ai.getNext()) ) {
5689 int fromParam, toParam;
5690 Node *source = a->getSourceNode (fromParam);
5691 Node *dest = a->getDestinationNode (toParam);
5692 ASSERT (dest == node);
5693 StandIn *ssi = source->getStandIn();
5694 if ((ssi) && (!ssi->isSelected())) {
5695 if ((dest->isA(ClassReceiverNode)) &&
5696 (source->isA(ClassTransmitterNode)) &&
5697 (EqualString (dest->getLabelString(),source->getLabelString()))) {
5698 } else {
5699 retVal = FALSE;
5700 if (report) {
5701 char msg[512];
5702 sprintf (msg,
5703 "Tool %s connects to unselected tool %s.\nSuggestion: ",
5704 dest->getNameString(), source->getNameString());
5705 strcat (msg,
5706 "Try the \'Edit/Select Tools/Select Connected\' option");
5707 ErrorMessage(msg);
5708 }
5709 break;
5710 }
5711 } else if (ssi) {
5712 if (!ws) {
5713 ws = (EditorWorkSpace*)ssi->getWorkSpace();
5714 } else if (ws != ssi->getWorkSpace()) {
5715 retVal = FALSE;
5716 if (report)
5717 ErrorMessage("Tool %s occupies a different page from %s.",
5718 dest->getNameString(), source->getNameString());
5719 break;
5720 }
5721 }
5722 }
5723 delete conns;
5724 }
5725
5726
5727 count = node->getOutputCount();
5728 for (i=1; ((retVal) && (i<=count)); i++) {
5729 Ark *a;
5730 List *orig = (List*)node->getOutputArks(i);
5731 conns = orig->dup();
5732 ListIterator ai(*conns);
5733 while ( (a = (Ark*)ai.getNext()) ) {
5734 int fromParam, toParam;
5735 Node *source = a->getSourceNode (fromParam);
5736 Node *dest = a->getDestinationNode (toParam);
5737 ASSERT (source == node);
5738 StandIn *dsi = dest->getStandIn();
5739 if ((dsi) && (!dsi->isSelected())) {
5740 if ((dest->isA(ClassReceiverNode)) &&
5741 (source->isA(ClassTransmitterNode)) &&
5742 (EqualString (dest->getLabelString(),source->getLabelString()))) {
5743 } else {
5744 retVal = FALSE;
5745 if (report) {
5746 char msg[512];
5747 sprintf (msg,
5748 "Tool %s has a connection from unselected tool %s.\n",
5749 source->getNameString(), dest->getNameString());
5750 strcat (msg, "Suggestion: "
5751 "Try the \'Edit/Select Tools/Select Connected\' option");
5752 ErrorMessage(msg);
5753 }
5754 break;
5755 }
5756 } else if (dsi) {
5757 if (!ws) {
5758 ws = (EditorWorkSpace*)dsi->getWorkSpace();
5759 } else if (ws != dsi->getWorkSpace()) {
5760 retVal = FALSE;
5761 if (report)
5762 ErrorMessage("Tool %s occupies a different page from %s.",
5763 source->getNameString(), dest->getNameString());
5764 break;
5765 }
5766 }
5767 }
5768 delete conns;
5769 }
5770 }
5771
5772 delete l;
5773 return retVal;
5774 }
5775 #endif
5776
5777 //
5778 // Prepare for a new decorator, but don't managed it yet.
5779 //
placeDecorator()5780 boolean EditorWindow::placeDecorator()
5781 {
5782 if (!this->addingDecorators)
5783 this->addingDecorators = new List;
5784
5785 DecoratorStyle *ds =
5786 DecoratorStyle::GetDecoratorStyle("Annotate", DecoratorStyle::DefaultStyle);
5787 ASSERT(ds);
5788 Decorator *d = ds->createDecorator(TRUE);
5789 ASSERT(d);
5790 d->setStyle (ds);
5791
5792 DecoratorInfo *dnd = new DecoratorInfo (this->network,
5793 (void*)this,
5794 (DragInfoFuncPtr)EditorWindow::SetOwner,
5795 (DragInfoFuncPtr)EditorWindow::DeleteSelections,
5796 (DragInfoFuncPtr)EditorWindow::Select);
5797 d->setDecoratorInfo(dnd);
5798
5799 this->addingDecorators->appendElement((void*)d);
5800 this->toolSelector->deselectAllTools();
5801
5802 //
5803 // Set the cursor to indicate placement
5804 //
5805 ASSERT(this->workSpace);
5806 this->workSpace->setCursor(UPPER_LEFT);
5807 return TRUE;
5808 }
5809
5810 //
5811 // Change the style of the selected decorator(s)
5812 //
5813 extern "C" void
EditorWindow_SetDecoratorStyleCB(Widget w,XtPointer clientData,XtPointer)5814 EditorWindow_SetDecoratorStyleCB (Widget w, XtPointer clientData, XtPointer)
5815 {
5816 EditorWindow *editor = (EditorWindow*)clientData;
5817 List *decors = editor->makeSelectedDecoratorList();
5818 long ud;
5819
5820 XtVaGetValues (w, XmNuserData, &ud, NULL);
5821 editor->setDecoratorStyle (decors, (DecoratorStyle*)ud);
5822 if (decors) delete decors;
5823 }
5824
setDecoratorStyle(List * decors,DecoratorStyle * ds)5825 void EditorWindow::setDecoratorStyle (List *decors, DecoratorStyle *ds)
5826 {
5827 if (!decors) return;
5828 ASSERT(ds);
5829
5830 //
5831 // For interactors, there is InteractorInstance which handles style
5832 // changes but, for decorators there is nothing. So, fetch the data,
5833 // make a new decorator, then replace the data.
5834 //
5835 ListIterator it(*decors);
5836 Decorator *dec;
5837 Symbol s = theSymbolManager->registerSymbol(ClassLabelDecorator);
5838 while ( (dec = (Decorator*)it.getNext()) ) {
5839 if (!dec->isA(s)) continue;
5840
5841 LabelDecorator *oldlab = (LabelDecorator*)dec;
5842 Dialog* sdtDiag = oldlab->getDialog();
5843 oldlab->associateDialog(NUL(Dialog*));
5844 WorkSpace *parent = oldlab->getWorkSpace();
5845 oldlab->unmanage();
5846 const char *val = oldlab->getLabelValue();
5847 int x,y;
5848 oldlab->getXYPosition (&x, &y);
5849 this->network->removeDecoratorFromList((void*)oldlab);
5850
5851 LabelDecorator *newlab = (LabelDecorator*)ds->createDecorator(TRUE);
5852 ASSERT(newlab);
5853 newlab->setStyle(ds);
5854
5855 DecoratorInfo *dnd = new DecoratorInfo (this->network,
5856 (void*)this,
5857 (DragInfoFuncPtr)EditorWindow::SetOwner,
5858 (DragInfoFuncPtr)EditorWindow::DeleteSelections,
5859 (DragInfoFuncPtr)EditorWindow::Select);
5860 newlab->setDecoratorInfo(dnd);
5861
5862 if ((val) && (val[0]))
5863 newlab->setLabel(val);
5864 newlab->setXYPosition(x,y);
5865 this->network->addDecoratorToList ((void*)newlab);
5866
5867 //
5868 // Transfer resource settings.
5869 //
5870 oldlab->transferResources(newlab);
5871 newlab->setFont(oldlab->getFont());
5872 newlab->associateDialog(sdtDiag);
5873 this->newDecorator (newlab, (EditorWorkSpace*)parent);
5874
5875 delete oldlab;
5876 }
5877
5878 this->network->setFileDirty();
5879 }
5880
5881 //
5882 // Edit/{Cut,Copy} means produce the chunk of .net/.cfg file the same as
5883 // would happen with drag-n-drop and store that chunk somewhere so that it
5884 // can be supplied to a requestor.
5885 //
cutSelectedNodes()5886 boolean EditorWindow::cutSelectedNodes()
5887 {
5888 if (this->copySelectedNodes(TRUE) == FALSE) {
5889 return FALSE;
5890 }
5891 this->removeSelectedNodes();
5892 this->setUndoActivation();
5893 return TRUE;
5894 }
5895
5896 #ifdef DXD_OS_NON_UNIX
5897 #define RD_FLAG "rb"
5898 #else
5899 #define RD_FLAG "r"
5900 #endif
5901
copySelectedNodes(boolean delete_property)5902 boolean EditorWindow::copySelectedNodes(boolean delete_property)
5903 {
5904 char msg[128];
5905 Display *d = XtDisplay(this->getRootWidget());
5906 Atom file_atom = XmInternAtom (d, NET_ATOM, False);
5907 Atom delete_atom = XmInternAtom (d, "DELETE", False);
5908 Screen *screen = XtScreen(this->getRootWidget());
5909 Window root = RootWindowOfScreen(screen);
5910
5911 int net_len, cfg_len;
5912 char* cfg_buffer;
5913 char* net_buffer = this->createNetFileFromSelection(net_len, &cfg_buffer, cfg_len);
5914 if (!net_buffer) return FALSE;
5915
5916 //
5917 // Safeguard: I don't know if this is necessary. Maybe calling XtOwnSelection
5918 // can have unintended consequences if you're already the selection owner?
5919 // Maybe libXt will tell me I lost the selection because someone took it?
5920 // So, I'll disown the selection before reasserting ownership.
5921 //
5922 Widget w = XtNameToWidget (this->getRootWidget(), "*optionSeparator");
5923 ASSERT (w);
5924 XtVaSetValues (w, XmNuserData, this, NULL);
5925 Time tstamp = XtLastTimestampProcessed(d);
5926 Window win = XGetSelectionOwner (d, file_atom);
5927 if ((win != None) && (XtWindow(w) == win))
5928 XtDisownSelection (w, file_atom, tstamp);
5929
5930 unsigned char del_buf[16];
5931 if (delete_property) strcpy ((char*)del_buf, "TRUE");
5932 else strcpy ((char*)del_buf, "FALSE");
5933 XChangeProperty (d, root, delete_atom, XA_STRING, 8, PropModeReplace,
5934 del_buf, strlen((char*)del_buf));
5935
5936 //
5937 // XtOwnSelection registers 3 callbacks but there is no clientData to pass.
5938 // Therefore I need some other way to get back the this pointer inside
5939 // these 3 callbacks. I am using XmNuserData in the widget for this purpose.
5940 // I picked such an obscure widget because I suspect that if the widget is the
5941 // root of some UIComponent, the XmNuserData slot will already be in use.
5942 //
5943 boolean retVal;
5944 if (XtOwnSelection (w, file_atom, tstamp,
5945 (XtConvertSelectionProc)EditorWindow_ConvertSelectionCB,
5946 (XtLoseSelectionProc)EditorWindow_LoseSelectionCB,
5947 (XtSelectionDoneProc)EditorWindow_SelectionDoneCB)) {
5948 this->pasteNodeCmd->activate();
5949 retVal = TRUE;
5950 } else {
5951 this->pasteNodeCmd->deactivate();
5952 retVal = FALSE;
5953 }
5954
5955 //
5956 // Assign to copied{Net,Cfg} after owning the selection in case owning also
5957 // makes you lose it.
5958 //
5959 if (this->copiedNet) delete this->copiedNet;
5960 this->copiedNet = (char *)net_buffer;
5961 if (this->copiedCfg) delete this->copiedCfg;
5962 this->copiedCfg = (char *)cfg_buffer;
5963
5964 return retVal;
5965 }
5966
5967 //
5968 // caller must free the returned memory
5969 //
createNetFileFromSelection(int & net_len,char ** cfg_out,int & cfg_len)5970 char* EditorWindow::createNetFileFromSelection(int& net_len, char** cfg_out, int& cfg_len)
5971 {
5972 char netfilename[256];
5973 char cfgfilename[256];
5974 FILE *netf;
5975 char msg[128];
5976
5977 net_len = cfg_len = 0;
5978 if (cfg_out) *cfg_out = NUL(char*);
5979
5980 //
5981 // It should be unnecessary to perform this check because command activation
5982 // should prevent being here if both counts are 0, however kbd accelerators
5983 // can get us here and we might not have any way of preempting that.
5984 //
5985 int nselected = this->getNodeSelectionCount();
5986 int dselected = 0;
5987 ListIterator it;
5988 Decorator *decor;
5989 FOR_EACH_NETWORK_DECORATOR(this->getNetwork(),decor,it)
5990 if (decor->isSelected()) dselected++;
5991 if ((dselected == 0) && (nselected == 0)) return NUL(char*);
5992
5993 //
5994 // Get 2 temp file names for the .net and .cfg files
5995 // FIXME: We need a DXApplication::getTmpFile(). The code
5996 // to form tmp file names off the tmp directory is used in several places.
5997 //
5998 const char *tmpdir = theDXApplication->getTmpDirectory();
5999 int tmpdirlen = STRLEN(tmpdir);
6000 if (!tmpdirlen) return NULL;
6001 if (tmpdir[tmpdirlen-1] == '/') {
6002 sprintf(netfilename, "%sdx%d.net", tmpdir, getpid());
6003 sprintf(cfgfilename, "%sdx%d.cfg", tmpdir, getpid());
6004 } else {
6005 sprintf(netfilename, "%s/dx%d.net", tmpdir, getpid());
6006 sprintf(cfgfilename, "%s/dx%d.cfg", tmpdir, getpid());
6007 }
6008 unlink (netfilename);
6009 unlink (cfgfilename);
6010
6011 if ((netf = fopen(netfilename, "a+")) == NULL) {
6012 sprintf (msg, "Copy failed: %s", strerror(errno));
6013 WarningMessage(msg);
6014 return NUL(char*);
6015 }
6016
6017 //
6018 // Save .net/.cfg into the temp directory;
6019 //
6020 this->network->printNetwork (netf, PrintCut);
6021 this->network->cfgPrintNetwork (cfgfilename, PrintCut);
6022 fclose(netf);
6023
6024
6025 //
6026 // Read the .net and .cfg back it, and save their contents
6027 //
6028 netf = NUL(FILE*);
6029 if ((netf = fopen(netfilename, RD_FLAG)) == NULL) {
6030 sprintf (msg, "Copy failed (fopen): %s", strerror(errno));
6031 WarningMessage(msg);
6032 return NUL(char*);
6033 }
6034
6035 unsigned char *cfg_buffer = NULL;
6036
6037 struct STATSTRUCT statb;
6038 if (cfg_out) {
6039 FILE *cfgf = fopen(cfgfilename, RD_FLAG);
6040 if ((cfgf) && (STATFUNC(cfgfilename, &statb) != -1)) {
6041 cfg_len = (unsigned int)statb.st_size;
6042 cfg_buffer = (unsigned char *)(cfg_len?new char[1+cfg_len]:NULL);
6043
6044 if (fread((char*)cfg_buffer, sizeof(char), cfg_len, cfgf) != cfg_len) {
6045 sprintf (msg, "Copy failed (fread): %s", strerror(errno));
6046 WarningMessage(msg);
6047 fclose(cfgf);
6048 delete cfg_buffer;
6049 return NUL(char*);
6050 }
6051 cfg_buffer[cfg_len] = '\0';
6052 fclose(cfgf);
6053 cfgf = NUL(FILE*);
6054 unlink (cfgfilename);
6055 }
6056 }
6057
6058 if (STATFUNC(netfilename, &statb) == -1) {
6059 sprintf (msg, "Copy failed (stat): %s", strerror(errno));
6060 WarningMessage(msg);
6061 fclose(netf);
6062 return NUL(char*);
6063 }
6064 net_len = (unsigned int)statb.st_size;
6065 if (!net_len) return NUL(char*);
6066 if (net_len > 63000) {
6067 WarningMessage ("Too much data. Try transferring in pieces.");
6068 fclose(netf);
6069 return NUL(char*);
6070 }
6071 unsigned char *net_buffer = (unsigned char *)(net_len?new char[1+net_len]:NULL);
6072
6073 if (fread((char*)net_buffer, sizeof(char), net_len, netf) != net_len) {
6074 sprintf (msg, "Copy failed (fread): %s", strerror(errno));
6075 WarningMessage(msg);
6076 fclose(netf);
6077 delete net_buffer;
6078 return NUL(char*);
6079 }
6080 net_buffer[net_len] = '\0';
6081 fclose(netf);
6082 unlink (netfilename);
6083
6084 if (cfg_out) *cfg_out = (char*)cfg_buffer;
6085 else if (cfg_buffer) delete cfg_buffer;
6086 return (char*)net_buffer;
6087 }
6088
6089 //
6090 // Edit/Paste means request the saved chunk of .net/.cfg text and do an
6091 // insertNetwork operation.
6092 //
pasteCopiedNodes()6093 boolean EditorWindow::pasteCopiedNodes()
6094 {
6095 Display *d = XtDisplay(this->getRootWidget());
6096 Atom file_atom = XmInternAtom (d, NET_ATOM, False);
6097 boolean proceed = TRUE;
6098
6099 //
6100 // command activation is handled clumsily for cut/copy/paste because
6101 // there is no notification when someone gains/loses selection ownership.
6102 //
6103 if (file_atom) {
6104 Window win = XGetSelectionOwner (d, file_atom);
6105 if (win == None) proceed = FALSE;
6106 } else
6107 proceed = FALSE;
6108
6109 if (!proceed) {
6110 this->pasteNodeCmd->deactivate();
6111 return FALSE;
6112 }
6113
6114 XtGetSelectionValue (this->getRootWidget(), file_atom, XA_STRING,
6115 (XtSelectionCallbackProc)EditorWindow_SelectionReadyCB, (XtPointer)this,
6116 XtLastTimestampProcessed(d));
6117 return TRUE;
6118 }
SetOwner(void * b)6119 void EditorWindow::SetOwner(void *b)
6120 {
6121 EditorWindow *ew = (EditorWindow*)b;
6122 Network *netw = ew->getNetwork();
6123 netw->setCPSelectionOwner(NUL(ControlPanel*));
6124 }
6125
DeleteSelections(void * b)6126 void EditorWindow::DeleteSelections(void *b)
6127 {
6128 EditorWindow *ew = (EditorWindow*)b;
6129 Command *cmd = ew->getDeleteNodeCmd();
6130
6131 cmd->execute();
6132 }
6133
Select(void * b)6134 void EditorWindow::Select(void *b)
6135 {
6136 EditorWindow *ew = (EditorWindow*)b;
6137 ew->setCommandActivation();
6138 }
6139
6140 #if EXPOSE_SET_SELECTION
setCopiedNet(const char * text)6141 void EditorWindow::setCopiedNet(const char* text)
6142 {
6143 Display *d = XtDisplay(this->getRootWidget());
6144 Atom file_atom = XmInternAtom (d, NET_ATOM, False);
6145 Atom delete_atom = XmInternAtom (d, "DELETE", False);
6146 Atom cfg_atom = XmInternAtom (d, CFG_ATOM, False);
6147 Screen *screen = XtScreen(this->getRootWidget());
6148 Window root = RootWindowOfScreen(screen);
6149 Time tstamp = XtLastTimestampProcessed(d);
6150
6151 Widget w = XtNameToWidget (this->getRootWidget(), "*optionSeparator");
6152 ASSERT (w);
6153
6154 if (this->copiedNet) {
6155 delete this->copiedNet;
6156 this->copiedNet = NUL(char*);
6157 this->pasteNodeCmd->deactivate();
6158 XtDisownSelection (w, file_atom, tstamp);
6159 }
6160 if (this->copiedCfg) {
6161 delete this->copiedCfg;
6162 this->copiedCfg = NUL(char*);
6163 }
6164
6165 if ((text) && (text[0])) {
6166 XtVaSetValues (w, XmNuserData, this, NULL);
6167 if (XtOwnSelection (w, file_atom, tstamp,
6168 (XtConvertSelectionProc)EditorWindow_ConvertSelectionCB,
6169 (XtLoseSelectionProc)EditorWindow_LoseSelectionCB,
6170 (XtSelectionDoneProc)EditorWindow_SelectionDoneCB))
6171 this->pasteNodeCmd->activate();
6172 else
6173 this->pasteNodeCmd->deactivate();
6174
6175 this->copiedNet = DuplicateString(text);
6176
6177 unsigned char del_buf[16];
6178 strcpy ((char*)del_buf, "FALSE");
6179 XChangeProperty (d, root, delete_atom, XA_STRING, 8, PropModeReplace,
6180 del_buf, strlen((char*)del_buf));
6181 }
6182 }
6183 #endif
6184
EditorWindow_ConvertSelectionCB(Widget w,Atom * selection,Atom * target,Atom * type,XtPointer * value,unsigned long * length,int * format)6185 boolean EditorWindow_ConvertSelectionCB(Widget w, Atom *selection, Atom *target,
6186 Atom *type, XtPointer *value, unsigned long *length, int *format)
6187 {
6188 Display *d = XtDisplay(w);
6189 Atom file_atom = XmInternAtom (d, NET_ATOM, False);
6190 Atom cfg_atom = XmInternAtom (d, CFG_ATOM, False);
6191 Screen *screen = XtScreen(w);
6192 Window root = RootWindowOfScreen(screen);
6193
6194 //
6195 // The this pointer was supposed to be in userData. If anyone else is using
6196 // userData on the widget, then this scheme won't work
6197 // because these callbacks lack a clientData argument.
6198 //
6199 XtPointer ud;
6200 XtVaGetValues (w, XmNuserData, &ud, NULL);
6201 EditorWindow *editor = (EditorWindow*)ud;
6202 ASSERT(editor);
6203
6204 //
6205 // FIXME: there was an ASSERT in place of this if but the ASSERT often failed.
6206 // It's meaning was: If this editor received a request for the selection,
6207 // then it must have asserted ownership of the selection. If it did that, then
6208 // it must have stored copiedNet. I don't understand how that can fail.
6209 // Maybe I'm doing something wrong in LoseSelectionCB, I don't know.
6210 //
6211 // I may have fixed it by disowning the selection prior to owning it. It turned
6212 // out that asking to own the selection if I already owned it, would produce
6213 // a call to my LoseSelection callback which would throw out selection data.
6214 //
6215 ASSERT (*selection == file_atom);
6216 if (editor->copiedNet) {
6217
6218
6219 *value = editor->copiedNet;
6220 *length = strlen(editor->copiedNet);
6221 *format = 8;
6222 *type = XA_STRING;
6223
6224 if (editor->copiedCfg)
6225 XChangeProperty (d, root, cfg_atom, XA_STRING, 8, PropModeReplace,
6226 (unsigned char*)editor->copiedCfg, strlen(editor->copiedCfg));
6227
6228 return TRUE;
6229 } else {
6230 XtDisownSelection (w, *selection, XtLastTimestampProcessed(XtDisplay(w)));
6231 editor->pasteNodeCmd->deactivate();
6232 return FALSE;
6233 }
6234 }
6235
EditorWindow_LoseSelectionCB(Widget w,Atom *)6236 void EditorWindow_LoseSelectionCB(Widget w, Atom *)
6237 {
6238 //
6239 // The this pointer was supposed to be in userData. If anyone else is using
6240 // userData on the widget, then this scheme won't work
6241 // because these callbacks lack a clientData argument.
6242 //
6243 XtPointer ud;
6244 XtVaGetValues (w, XmNuserData, &ud, NULL);
6245 EditorWindow *editor = (EditorWindow*)ud;
6246 ASSERT(editor);
6247
6248 if (editor->copiedNet) {
6249 delete editor->copiedNet;
6250 editor->copiedNet = NUL(char*);
6251 }
6252 if (editor->copiedCfg) {
6253 delete editor->copiedCfg;
6254 editor->copiedCfg = NUL(char*);
6255 }
6256 editor->pasteNodeCmd->deactivate();
6257 }
6258
EditorWindow_SelectionDoneCB(Widget w,Atom *,Atom *)6259 void EditorWindow_SelectionDoneCB(Widget w, Atom *, Atom *) {}
6260
EditorWindow_SelectionReadyCB(Widget w,XtPointer clientData,Atom * selection,Atom * type,XtPointer value,unsigned long * length,int * format)6261 void EditorWindow_SelectionReadyCB (Widget w, XtPointer clientData, Atom *selection,
6262 Atom *type, XtPointer value, unsigned long *length, int *format)
6263 {
6264 EditorWindow *editor = (EditorWindow*)clientData;
6265 int status;
6266 FILE *netf;
6267 Display *d = XtDisplay(editor->getRootWidget());
6268 Atom file_atom = XmInternAtom (d, NET_ATOM, False);
6269 Atom cfg_atom = XmInternAtom (d, CFG_ATOM, False);
6270 Screen *screen = XtScreen(editor->getRootWidget());
6271 Window root = RootWindowOfScreen(screen);
6272 unsigned long bytes_after;
6273 char *net_buffer;
6274 Atom actual_type;
6275 int actual_format;
6276 unsigned long n_items;
6277 char msg[128];
6278
6279 //
6280 // Get temp file names
6281 //
6282 char net_file_name[256];
6283 char cfg_file_name[256];
6284 //
6285 // It's good that this file name is formed using getTmpDirectory()
6286 // because later we're going to check to see if the file name
6287 // begins with the tmp directory and if so, leave it out of
6288 // the list of recently-referenced files.
6289 //
6290 const char *tmpdir = theDXApplication->getTmpDirectory();
6291 int tmpdirlen = STRLEN(tmpdir);
6292 if (!tmpdirlen) return ;
6293 if (tmpdir[tmpdirlen-1] == '/') {
6294 sprintf(net_file_name, "%sdx%d.net", tmpdir, getpid());
6295 sprintf(cfg_file_name, "%sdx%d.cfg", tmpdir, getpid());
6296 } else {
6297 sprintf(net_file_name, "%s/dx%d.net", tmpdir, getpid());
6298 sprintf(cfg_file_name, "%s/dx%d.cfg", tmpdir, getpid());
6299 }
6300 unlink (net_file_name);
6301 unlink (cfg_file_name);
6302
6303
6304 //
6305 // Put the file contents into the files
6306 //
6307 if ((netf = fopen(net_file_name, "w")) == NULL) {
6308 sprintf (msg, "Paste failed (fopen): %s", strerror(errno));
6309 WarningMessage(msg);
6310 return ;
6311 }
6312 fwrite ((char*)value, sizeof(char), *length, netf);
6313 fclose(netf);
6314 XtFree((char*)value);
6315
6316 status = XGetWindowProperty (d, root, cfg_atom, 0,
6317 63000>>2, False, XA_STRING, &actual_type,
6318 &actual_format, &n_items, &bytes_after,
6319 (unsigned char **)&net_buffer);
6320
6321 if ((status == Success) && (net_buffer)) {
6322 if ((netf = fopen(cfg_file_name, "w")) == NULL) {
6323 sprintf (msg, "Paste failed (fopen): %s", strerror(errno));
6324 WarningMessage(msg);
6325 unlink (cfg_file_name);
6326 return ;
6327 }
6328 fwrite (net_buffer, sizeof(char), n_items, netf);
6329 fclose(netf);
6330 XFree(net_buffer);
6331 unlink (cfg_file_name);
6332 }
6333
6334
6335 editor->setPendingPaste (net_file_name, NUL(char*), TRUE);
6336
6337 unlink (net_file_name);
6338
6339 unsigned char *del_buf;
6340 Atom delete_atom = XmInternAtom (d, "DELETE", False);
6341 status = XGetWindowProperty (d, root, delete_atom, 0, 4, False, XA_STRING,
6342 &actual_type, &actual_format, &n_items, &bytes_after, &del_buf);
6343 if ((status == Success) && (del_buf) && (!strcmp((char*)del_buf, "FALSE"))) {
6344 } else {
6345 XDeleteProperty (d, root, file_atom);
6346 XDeleteProperty (d, root, cfg_atom);
6347 //
6348 // Force no one to own the selection. XtDisown ought to be superfluous,
6349 // but I'm not sure how/if the intrinsics find out about things like this
6350 // done thru Xlib. We're trying to make sure nobody has the selection,
6351 // and also to let our own intrinsics know we don't.
6352 //
6353 Time tstamp = XtLastTimestampProcessed(d);
6354 XtDisownSelection (w, file_atom, tstamp);
6355 XSetSelectionOwner (d, file_atom, None, CurrentTime);
6356 editor->pasteNodeCmd->deactivate();
6357 }
6358 if (del_buf) XFree(del_buf);
6359
6360
6361 editor->workSpace->setCursor(UPPER_LEFT);
6362 }
6363
6364 //
6365 // Broken out of SelectionReadyCB so that it can be reused by UndoDeletion
6366 //
setPendingPaste(const char * net_file_name,const char * cfg_file_name,boolean ignoreUndefinedModules)6367 boolean EditorWindow::setPendingPaste (const char* net_file_name,
6368 const char* cfg_file_name, boolean ignoreUndefinedModules)
6369 {
6370 //
6371 // Prepare a new network
6372 //
6373 if (this->addingDecorators) {
6374 ListIterator it(*this->addingDecorators);
6375 Decorator *dec;
6376 while ( (dec = (Decorator*)it.getNext()) ) delete dec;
6377 this->addingDecorators->clear();
6378 delete this->addingDecorators;
6379 this->addingDecorators = NULL;
6380 }
6381
6382 if (this->pendingPaste) delete this->pendingPaste;
6383 this->pendingPaste = theDXApplication->newNetwork(TRUE);
6384 ASSERT(this->pendingPaste);
6385 if (!this->pendingPaste->readNetwork (net_file_name, NULL, TRUE)) {
6386 delete this->pendingPaste;
6387 this->pendingPaste = NULL;
6388 WarningMessage ("Paste failed");
6389 unlink (net_file_name);
6390 return FALSE;
6391 }
6392 this->toolSelector->deselectAllTools();
6393 return TRUE;
6394 }
6395
6396 //
6397 // Find the last selected transmitter node. If it no longer exists,
6398 // then find the most recently placed one. This is useful for the
6399 // ReceiverNode, which needs to no the most recent Transmitter to attach
6400 // to.
6401 //
getMostRecentTransmitterNode()6402 TransmitterNode *EditorWindow::getMostRecentTransmitterNode()
6403 {
6404 Node *node = NULL;
6405
6406 //
6407 // Find all transmitters
6408 //
6409 List *l = this->network->makeClassifiedNodeList(ClassTransmitterNode);
6410
6411 //
6412 // Find
6413 // 1) the one that is in lastSelectedTransmitter, or
6414 // 2) the one with the highest instance number.
6415 //
6416 if (l) {
6417 Node *last=NULL;
6418 ListIterator iter(*l);
6419
6420 //
6421 // Look for one that matches the last selected node.
6422 // Note, that we aren't sure that lastSelectedTransmitter is still
6423 // in the network.
6424 //
6425 if (this->lastSelectedTransmitter) {
6426 while ( (last = (Node*)iter.getNext()) ) {
6427 if (last == this->lastSelectedTransmitter) {
6428 node = last;
6429 break;
6430 }
6431 }
6432 }
6433 if (!node) { // If none found that match lastSelectedTransmitter
6434 int maxinst = 0;
6435 iter.setList(*l);
6436 while ( (node = (Node*)iter.getNext()) ) {
6437 int newinst = node->getInstanceNumber();
6438 if ((maxinst == 0) || (newinst > maxinst)) {
6439 maxinst = newinst;
6440 last = node;
6441 }
6442 }
6443 node = last;
6444 }
6445 delete l;
6446 }
6447
6448 return (TransmitterNode*)node;
6449
6450 }
6451
6452 //
6453 // Visit the most recently executed nodes changing their label color.
6454 // Check every addition to the list for a connection to Transmitter. If
6455 // found add the Transmitter to the list. Then add all corresponding
6456 // Receivers to the list also.
6457 //
showExecutedNodes()6458 boolean EditorWindow::showExecutedNodes()
6459 {
6460 this->deselectAllNodes();
6461
6462 if (!this->executed_nodes) return FALSE;
6463 if (!this->executed_nodes->getSize()) return FALSE;
6464
6465 ListIterator it;
6466 Node* n;
6467
6468 //
6469 // See if the network contains any moduless nodes
6470 //
6471 List modless;
6472 Symbol sym;
6473 Symbol interactor_sym;
6474 if (!this->transmitters_added) {
6475 //
6476 // Search the network for nodes which aren't backed up by modules.
6477 // These will have be to selected depending on what else executed.
6478 // It does no good to add DXLOutputNode to the list because we're doing
6479 // a bottom-up search. DXLOutputNode has no outputs. I tried adding
6480 // ClassNondrivenInteractorNode instead of InteractorNode. The problem
6481 // there is that some InteractorNodes (subclassing off DrivenNode and not
6482 // subclassing off NondrivenInteractorNode) are really not driven, so you
6483 // have to test each one using isDataDriven().
6484 //
6485 sym = theSymbolManager->registerSymbol(ClassMacroParameterNode);
6486 modless.appendElement((void*)sym);
6487 sym = theSymbolManager->registerSymbol(ClassTransmitterNode);
6488 modless.appendElement((void*)sym);
6489 sym = theSymbolManager->registerSymbol(ClassReceiverNode);
6490 modless.appendElement((void*)sym);
6491 sym = theSymbolManager->registerSymbol(ClassDXLInputNode);
6492 modless.appendElement((void*)sym);
6493 interactor_sym = sym = theSymbolManager->registerSymbol(ClassInteractorNode);
6494 modless.appendElement((void*)sym);
6495
6496
6497 ListIterator it(modless);
6498 boolean found_some = FALSE;
6499 while ((found_some == FALSE) && (sym = (Symbol)(long)it.getNext())) {
6500 const char* cp = theSymbolManager->getSymbolString(sym);
6501 ASSERT ((cp) && (cp[0]));
6502 List* nodes = this->network->makeClassifiedNodeList(cp);
6503 if ((nodes) && (nodes->getSize()))
6504 found_some = TRUE;
6505 if (nodes)
6506 delete nodes;
6507 }
6508 if (found_some == FALSE)
6509 this->transmitters_added = TRUE;
6510 }
6511
6512 //
6513 // Loop until no change to the list of executed_nodes is made. Must loop
6514 // because if one moduleless node is added, that guy could be connected to
6515 // others who should be added, but we won't know until the next pass.
6516 //
6517 // FIXME: would someone please rewrite this loop in the form of a recursive
6518 // subroutine call.
6519 //
6520 boolean change_made = TRUE;
6521 List appendables;
6522 List recent1;
6523 List recent2;
6524 boolean first_time = TRUE;
6525 while ((!this->transmitters_added) && (change_made)) {
6526 int i, j;
6527
6528 change_made = FALSE;
6529
6530 //
6531 // First time thru the loop look at every executed node. On subsequent
6532 // iterations, look only at those nodes which were added on the previous
6533 // iteration.
6534 //
6535 if (first_time) it.setList(*this->executed_nodes);
6536 else it.setList(recent1);
6537
6538 while ( (n = (Node*)it.getNext()) ) {
6539 int numParam = n->getInputCount();
6540 for (i = 1; i <= numParam; ++i) {
6541 if (n->isInputConnected(i)) {
6542 Ark *a;
6543 List *arcs = (List *)n->getInputArks(i);
6544 for (j = 1; (a = (Ark*)arcs->getElement(j)); ++j) {
6545 int paramInd;
6546 Node *srcNode = a->getSourceNode(paramInd);
6547 boolean moduleless_node = FALSE;
6548
6549 ListIterator mit(modless);
6550 while ( (sym = (Symbol)(long)mit.getNext()) ) {
6551 if (srcNode->isA(sym)) {
6552 if (sym == interactor_sym) {
6553 InteractorNode* in = (InteractorNode*)srcNode;
6554 if (in->isDataDriven() == FALSE) {
6555 moduleless_node = TRUE;
6556 break;
6557 }
6558 } else {
6559 moduleless_node = TRUE;
6560 break;
6561 }
6562 }
6563 }
6564
6565 if (moduleless_node) {
6566 if (!appendables.isMember((void*)srcNode)) {
6567 appendables.appendElement((void*)srcNode);
6568 recent2.appendElement((void*)srcNode);
6569 change_made = TRUE;
6570 }
6571 }
6572 }
6573 }
6574 }
6575 }
6576 recent1.clear();
6577 it.setList(recent2);
6578 while ( (n = (Node*)it.getNext()) )
6579 recent1.appendElement((void*)n);
6580 recent2.clear();
6581 first_time = FALSE;
6582 }
6583 it.setList(appendables);
6584 while ( (n = (Node*)it.getNext()) )
6585 this->executed_nodes->appendElement((void*)n);
6586 this->transmitters_added = TRUE;
6587
6588 it.setList(*this->executed_nodes);
6589 while ( (n = (Node*)it.getNext()) )
6590 this->selectNode(n, TRUE, FALSE);
6591
6592 return TRUE;
6593 }
6594
6595 //
6596 // A counterpart to newNode(). Used only for vpe annotation.
6597 //
newDecorator(Decorator * dec,EditorWorkSpace * where)6598 void EditorWindow::newDecorator (Decorator* dec, EditorWorkSpace* where)
6599 {
6600
6601 #if WORKSPACE_PAGES
6602 const char* cp;
6603 VPEAnnotator *vpea = (VPEAnnotator*)dec;
6604 if ( (cp = vpea->getGroupName(theSymbolManager->getSymbol(PAGE_GROUP))) ) {
6605 EditorWorkSpace *page = this->getPage(cp);
6606 ASSERT(page);
6607 //
6608 // If page is equal to the current page, then manage the decorator.
6609 //
6610 int page_num = this->workSpace->getCurrentPage();
6611 EditorWorkSpace* ews = this->workSpace;
6612 if (page_num)
6613 ews = (EditorWorkSpace*)this->workSpace->getElement(page_num);
6614 if (ews == page)
6615 vpea->manage(page);
6616 else
6617 page->setMembersInitialized(FALSE);
6618 } else {
6619 EditorWorkSpace* current_page = where;
6620 if (!current_page) {
6621 int page = this->workSpace->getCurrentPage();
6622 if (page)
6623 current_page = (EditorWorkSpace*)this->workSpace->getElement(page);
6624 else
6625 current_page = this->workSpace;
6626 }
6627 GroupRecord* grec = this->getGroupOfWorkSpace(current_page);
6628 Symbol page_sym = theSymbolManager->getSymbol(PAGE_GROUP);
6629 if (grec) vpea->setGroupName (grec, page_sym);
6630 if (current_page->getRootWidget())
6631 vpea->manage(current_page);
6632 else
6633 current_page->setMembersInitialized(FALSE);
6634 }
6635 #else
6636 if ((where) && (where->getRootWidget()))
6637 dec->manage(where);
6638 else if (this->workSpace->getRootWidget())
6639 dec->manage(this->workSpace);
6640 #endif
6641 }
6642
6643 //
6644 // EditorWindow maintains a list of greened nodes so that we can go back
6645 // sometime later and see what executed. Several steps are required to
6646 // unset the list and the lis must be unset in several situations so
6647 // encapsulate it here.
6648 //
resetExecutionList()6649 void EditorWindow::resetExecutionList()
6650 {
6651 if (this->executed_nodes) this->executed_nodes->clear();
6652 this->showExecutedCmd->deactivate();
6653 this->transmitters_added = FALSE;
6654 }
6655
6656 #if WORKSPACE_PAGES
resetErrorList(boolean reset_all)6657 void EditorWindow::resetErrorList(boolean reset_all)
6658 {
6659 if (reset_all) {
6660 if (this->errored_standins) delete this->errored_standins;
6661 this->errored_standins = NUL(List*);
6662 } else if (this->errored_standins) {
6663 if (this->errored_standins->getSize() == 0) {
6664 delete this->errored_standins;
6665 this->errored_standins = NUL(List*);
6666 }
6667 }
6668
6669 //
6670 // reset all page tab colors keeping those yellow which
6671 // still have yellow standins
6672 //
6673 List yellow_tabs;
6674 if (this->errored_standins) {
6675 ListIterator it(*this->errored_standins);
6676 StandIn* si;
6677 while ( (si = (StandIn*)it.getNext()) ) {
6678 WorkSpace* page = si->getWorkSpace();
6679 yellow_tabs.appendElement((void*)page);
6680 }
6681 }
6682
6683 DictionaryIterator di(*this->pageSelector);
6684 EditorWorkSpace* ews;
6685 while ( (ews = (EditorWorkSpace*)di.getNextDefinition()) )
6686 if (yellow_tabs.isMember((void*)ews) == FALSE)
6687 this->pageSelector->highlightTab (ews, EditorWindow::REMOVEHIGHLIGHT);
6688 }
6689 #endif
6690
6691 #if WORKSPACE_PAGES
6692
getPageMemberCount(WorkSpace * page)6693 int EditorWindow::getPageMemberCount(WorkSpace* page)
6694 {
6695 const char* page_name = NUL(char*);
6696 int i,count = this->pageSelector->getSize();
6697 for (i=1; i<=count; i++) {
6698 if (page == this->pageSelector->getDefinition(i)) {
6699 page_name = this->pageSelector->getStringKey(i);
6700 break;
6701 }
6702 }
6703 if (page != this->workSpace) {
6704 ASSERT(page_name);
6705 }
6706
6707 int kidCnt = 0;
6708 ListIterator it;
6709 Node* node;
6710 Decorator* dec;
6711 Symbol psym = theSymbolManager->getSymbol(PAGE_GROUP);
6712 FOR_EACH_NETWORK_NODE (this->network, node, it) {
6713 const char* nodes_page_name = node->getGroupName(psym);
6714 if ((!nodes_page_name) && ((!page) || (page == this->workSpace))) {
6715 kidCnt++;
6716 } else {
6717 if (EqualString(page_name, nodes_page_name)) {
6718 kidCnt++;
6719 }
6720 }
6721 }
6722
6723 FOR_EACH_NETWORK_DECORATOR (this->network, dec, it) {
6724 VPEAnnotator* vpea = (VPEAnnotator*)dec;
6725 const char* nodes_page_name = vpea->getGroupName(psym);
6726 if ((!nodes_page_name) && ((!page) || (page == this->workSpace))) {
6727 kidCnt++;
6728 } else {
6729 if (EqualString(page_name, nodes_page_name)) {
6730 kidCnt++;
6731 }
6732 }
6733 }
6734 return kidCnt;
6735 }
6736
populatePage(EditorWorkSpace * ews)6737 void EditorWindow::populatePage(EditorWorkSpace* ews)
6738 {
6739 Symbol psym = theSymbolManager->getSymbol(PAGE_GROUP);
6740 GroupRecord* grec = this->getGroupOfWorkSpace(ews);
6741
6742 //
6743 // There is a page button associated with a workspace and that workspace
6744 // has no group? Shouldn't happen unless you just haven't made the group yet.
6745 //
6746 //if (!grec) return ;
6747
6748 const char* page_name = (grec?grec->getName():NUL(char*));
6749 Node* node;
6750 ListIterator it;
6751 Decorator* dec;
6752
6753 //
6754 // Loop over nodes looking for those belonging to the page. When found
6755 // check to see if the nodes have standins. This tells us if we need to
6756 // do work to populate the page.
6757 //
6758 boolean standins_created = FALSE;
6759 if (ews->membersInitialized() == FALSE) {
6760 FOR_EACH_NETWORK_NODE (this->network, node, it) {
6761 const char* cp = node->getGroupName(psym);
6762 if (((cp == NUL(char*)) && (page_name == NUL(char*))) ||
6763 (EqualString(cp, page_name))) {
6764 StandIn* si = node->getStandIn();
6765 if (!si) {
6766 if (!standins_created)
6767 ews->beginManyPlacements();
6768 node->newStandIn(ews);
6769 standins_created = TRUE;
6770 if (node == this->executing_node)
6771 this->highlightNode(node, EditorWindow::EXECUTEHIGHLIGHT);
6772 } else {
6773 //
6774 // I would like to put a break here but I can't assume that if
6775 // the page contains 1 standin, that all nodes in the page have
6776 // standins. Reason: Edit/Insert Visual Program could have
6777 // placed new standins here which haven't been created yet.
6778 //
6779 //break;
6780 }
6781 }
6782 }
6783
6784 //
6785 // This says we're not going to toggle lineRouting/overlap if we're adding
6786 // only decorators. Good?
6787 //
6788 FOR_EACH_NETWORK_DECORATOR(this->network,dec,it) {
6789 if (dec->getRootWidget()) continue;
6790 VPEAnnotator* vpea = (VPEAnnotator*)dec;
6791 const char* cp = vpea->getGroupName(psym);
6792 if (((cp == NUL(char*)) && (page_name == NUL(char*))) ||
6793 (EqualString(cp, page_name))) {
6794 vpea->manage(ews);
6795 }
6796 }
6797 }
6798
6799 if (standins_created) {
6800 boolean old_value = this->creating_new_network;
6801 this->creating_new_network = TRUE;
6802 FOR_EACH_NETWORK_NODE (this->network, node, it) {
6803 const char* cp = node->getGroupName(psym);
6804 if (((cp == NUL(char*)) && (page_name == NUL(char*))) ||
6805 (EqualString(cp, page_name))) {
6806 StandIn* si = node->getStandIn();
6807 ASSERT(si);
6808 int icnt = node->getInputCount();
6809 int i;
6810 for (i=1 ; i<=icnt ; i++) {
6811 List* arcs = (List *)node->getInputArks(i);
6812 Ark* a;
6813 int j;
6814 for (j = 1; (a = (Ark*) arcs->getElement(j)); j++) {
6815 int dummy;
6816 Node* tn = a->getSourceNode(dummy);
6817 ASSERT(tn);
6818 if (tn->getStandIn() == NUL(StandIn*)) continue;
6819 if (a->getArkStandIn() == NUL(ArkStandIn*))
6820 this->notifyArk(a);
6821 }
6822 si->drawTab(i, FALSE);
6823 }
6824 }
6825 }
6826 this->creating_new_network = old_value;
6827 ews->endManyPlacements();
6828 ews->setMembersInitialized();
6829 }
6830 }
6831 #endif
6832
6833 //
6834 // Change all nodes and decorators in tmpnet so that they think they live
6835 // in ews and belong to the corresponding group. The is used when dropping
6836 // a selection of network onto a page tab. An apparent wierdness here is that
6837 // we'll change all nodes in tmpnet without regard to their current grouping.
6838 // That should be OK however, because there is no way using drag-n-drop to
6839 // select nodes which live in more than 1 page/group.
6840 // The try_current_page argument means that we should allow the operation to proceed
6841 // if it looks like we're trying to paste into a page with no group operation. Letting
6842 // it go ahead will put the nodes in the currently selected page. That's good behavior
6843 // in the case of Edit/Paste but bad behavior when dropping onto a page tab.
6844 //
pagifyNetNodes(Network * tmpnet,EditorWorkSpace * ews,boolean try_current_page)6845 boolean EditorWindow::pagifyNetNodes
6846 (Network* tmpnet, EditorWorkSpace* ews, boolean try_current_page)
6847 {
6848 Symbol groupID = theSymbolManager->getSymbol(PAGE_GROUP);
6849
6850 //
6851 // It's not OK for grec to be NULL because if it's NULL, then when
6852 // Network::mergeNetworks() works on tmpnet, it won't be able to adjust
6853 // the group pointers. Allow the operation to proceed if there is no
6854 // group and there is also no workspace. In that case just erase the
6855 // group information and let the chips fall where they may. That should
6856 // mean that everything will be placed in whatever is the current page.
6857 //
6858 GroupRecord* grec = this->getGroupOfWorkSpace(ews);
6859 const char* group_name = NUL(char*);
6860 if (grec) {
6861 group_name = grec->getName();
6862 }
6863 if ((!group_name) && (!try_current_page)) return FALSE;
6864
6865
6866 //
6867 // Find the page manager from the old net and make a group record for the
6868 // new group name.
6869 //
6870 Dictionary* dict = tmpnet->getGroupManagers();
6871 GroupManager* page_mgr = (GroupManager*)dict->findDefinition(groupID);
6872 //
6873 // This can only fail if the group already exists, which is OK.
6874 //
6875 GroupRecord* new_grec = NUL(GroupRecord*);
6876 if (group_name) {
6877 page_mgr->createGroup (group_name, tmpnet);
6878 new_grec = page_mgr->getGroup(group_name);
6879 if (!new_grec) return FALSE;
6880 }
6881
6882
6883 Node* node;
6884 ListIterator li;
6885 Decorator* dec;
6886 FOR_EACH_NETWORK_NODE(tmpnet, node, li) {
6887 node->setGroupName(new_grec, groupID);
6888 }
6889 FOR_EACH_NETWORK_DECORATOR(tmpnet, dec, li) {
6890 VPEAnnotator* vpea = (VPEAnnotator*)dec;
6891 vpea->setGroupName(new_grec, groupID);
6892 }
6893 return TRUE;
6894 }
6895
pagifySelectedNodes(EditorWorkSpace * ews)6896 boolean EditorWindow::pagifySelectedNodes(EditorWorkSpace* ews)
6897 {
6898 Symbol groupID = theSymbolManager->getSymbol(PAGE_GROUP);
6899
6900 GroupRecord* grec = this->getGroupOfWorkSpace(ews);
6901 const char* group_name = NUL(char*);
6902 if (grec) group_name = grec->getName();
6903 if (!group_name) return FALSE;
6904
6905 List* selno = this->makeSelectedNodeList();
6906 List* seldec = this->makeSelectedDecoratorList();
6907 EditorWorkSpace* selectedWS = NUL(EditorWorkSpace*);
6908
6909 if ((selno) && (selno->getSize())) {
6910 Node* n = (Node*)selno->getElement(1);
6911 StandIn* si = (StandIn*)n->getStandIn();
6912 selectedWS = (EditorWorkSpace*)si->getWorkSpace();
6913 } else if ((seldec) && (seldec->getSize())) {
6914 Decorator* dec = (Decorator*)seldec->getElement(1);
6915 selectedWS = (EditorWorkSpace*)dec->getWorkSpace();
6916 }
6917
6918
6919 if (selectedWS) selectedWS->beginManyPlacements();
6920 if (seldec) {
6921 ListIterator it(*seldec);
6922 VPEAnnotator* dec;
6923 while ( (dec = (VPEAnnotator*)it.getNext()) )
6924 dec->setGroupName(grec, groupID);
6925 this->moveDecorators (ews, seldec, 20, 20, selno);
6926 }
6927 if (selno) {
6928 ListIterator it(*selno);
6929 Node* n;
6930 while ( (n = (Node*)it.getNext()) )
6931 n->setGroupName(grec, groupID);
6932 this->moveStandIns (ews, selno, 20, 20, seldec);
6933 }
6934 if (selectedWS) selectedWS->endManyPlacements();
6935 if (selno) delete selno;
6936 if (seldec) delete seldec;
6937
6938 this->setCommandActivation();
6939 return TRUE;
6940 }
6941
configurePage()6942 boolean EditorWindow::configurePage()
6943 {
6944 this->pageSelector->postPageNameDialog();
6945 return TRUE;
6946 }
postMoveSelectedDialog()6947 boolean EditorWindow::postMoveSelectedDialog()
6948 {
6949 this->pageSelector->postMoveNodesDialog();
6950 this->setCommandActivation();
6951 return TRUE;
6952 }
6953
6954 //
6955 // Break any arc which connects a selected node to an unselected node.
6956 // Replace the arc with transmitter/receiver combination.
6957 //
autoChopSelectedNodes()6958 boolean EditorWindow::autoChopSelectedNodes()
6959 {
6960 List* sellist = this->makeSelectedNodeList();
6961 if ((sellist == NUL(List*)) || (sellist->getSize() == 0))
6962 return TRUE;
6963
6964 Network* net = this->getNetwork();
6965 Dictionary tmits;
6966 Dictionary rcvrs;
6967 boolean status = net->chopArks(sellist, &tmits, &rcvrs);
6968
6969 DictionaryIterator di(rcvrs);
6970 Node* n;
6971 while ( (n = (Node*)di.getNextDefinition()) ) {
6972 StandIn* si = n->getStandIn();
6973 if (si) {
6974 List* arcs = (List *)n->getOutputArks(1);
6975 int j;
6976 Ark* a;
6977 for (j = 1; (a = (Ark*) arcs->getElement(j)) ; j++)
6978 this->notifyArk(a);
6979 si->drawTab(1, FALSE);
6980 }
6981 }
6982 delete sellist;
6983
6984 if (this->selectConnectedNodeCmd->isActive())
6985 this->selectConnectedNodeCmd->execute();
6986
6987 return status;
6988 }
6989
autoFuseSelectedNodes()6990 boolean EditorWindow::autoFuseSelectedNodes()
6991 {
6992 ListIterator it;
6993 Node* n;
6994 List rcvrs;
6995 int dummy;
6996
6997 List* sellist = this->makeSelectedNodeList();
6998 if ((sellist == NUL(List*)) || (sellist->getSize() == 0))
6999 return TRUE;
7000
7001 Network* net = this->getNetwork();
7002
7003 it.setList(*sellist);
7004 while ( (n = (Node*)it.getNext()) )
7005 if (n->isA(ClassReceiverNode))
7006 rcvrs.appendElement((void*)n);
7007
7008 //
7009 // If the original list contains only a transmitter(s), then augment the
7010 // list by adding all the receivers they're feeding. In other words, if
7011 // the user selects a transmitter and asks to rewire it, then assume
7012 // she wants to get rid of all corresponding receivers.
7013 //
7014 if (rcvrs.getSize() == 0) {
7015 it.setList(*sellist);
7016 while ( (n = (Node*)it.getNext()) ) {
7017 if (n->isA(ClassTransmitterNode) == FALSE) continue;
7018 List* orig = (List*)n->getOutputArks(1);
7019 if ((!orig) || (orig->getSize() == 0)) continue;
7020 ListIterator ai(*orig);
7021 Ark* a;
7022 while ( (a = (Ark*)ai.getNext()) ) {
7023 Node* rcvr = a->getDestinationNode(dummy);
7024 ASSERT(rcvr->isA(ClassReceiverNode));
7025 rcvrs.appendElement((void*)rcvr);
7026 }
7027 }
7028 }
7029
7030 //
7031 // Make a new list by augmenting the original. For every
7032 // non-(transmitter/receiver) node , if its got no selected
7033 // receiver node inputs, then add all its receiver node inputs.
7034 //
7035 it.setList(*sellist);
7036 while ( (n = (Node*)it.getNext()) ) {
7037 if (n->isA(ClassTransmitterNode)) continue;
7038 if (n->isA(ClassReceiverNode)) continue;
7039 int icnt = n->getInputCount();
7040 int i;
7041 List toadd;
7042 boolean unusable_receiver = FALSE;
7043 for (i=1; i<=icnt; i++) {
7044 List* orig = (List*)n->getInputArks(i);
7045 if ((!orig) || (orig->getSize() == 0)) continue;
7046 ASSERT(orig->getSize() == 1);
7047 Ark* a = (Ark*)orig->getElement(1);;
7048 Node* src = a->getSourceNode(dummy);
7049 if (src->isA(ClassReceiverNode)) {
7050 List* oa = (List*)src->getOutputArks(1);
7051 ASSERT(oa);
7052 if (oa->getSize() == 1) {
7053 toadd.appendElement((void*)src);
7054 } else {
7055 ListIterator oi(*oa);
7056 Ark* a;
7057 boolean included = TRUE;
7058 while ( (a = (Ark*)oi.getNext()) ) {
7059 Node* dest = a->getDestinationNode(dummy);
7060 if (sellist->isMember((void*)dest) == FALSE) {
7061 included = FALSE;
7062 break;
7063 }
7064 }
7065 if (included)
7066 toadd.appendElement((void*)src);
7067 }
7068 StandIn* si = src->getStandIn();
7069 if (si) unusable_receiver = si->isSelected();
7070 }
7071 if (unusable_receiver) break;
7072 }
7073 if (unusable_receiver == FALSE) {
7074 ListIterator ta(toadd);
7075 Node* add;
7076 while ( (add = (Node*)ta.getNext()) ) {
7077 if (rcvrs.isMember(add) == FALSE)
7078 rcvrs.appendElement((void*)add);
7079 }
7080 }
7081 }
7082
7083 //
7084 // Network::replaceInputArks() operates stritly on
7085 // the basis of the Receviers it encounters
7086 //
7087 boolean status = net->replaceInputArks(&rcvrs, NUL(List*));
7088
7089 delete sellist;
7090
7091 return status;
7092 }
7093
toggleHitDetection()7094 boolean EditorWindow::toggleHitDetection()
7095 {
7096 WorkSpaceInfo *wsinfo = this->workSpace->getInfo();
7097 ToggleButtonInterface* tbi = (ToggleButtonInterface*)
7098 this->hitDetectionOption;
7099 this->hit_detection = tbi->getState();
7100 wsinfo->setPreventOverlap(this->hit_detection);
7101 this->workSpace->installInfo(NULL);
7102 return TRUE;
7103 }
7104
7105 String EditorWindow::SequenceNet[] = {
7106 #include "sequence.h"
7107 };
7108
unjavifyNetwork()7109 boolean EditorWindow::unjavifyNetwork()
7110 {
7111 List* rlist = this->network->makeClassifiedNodeList(ClassReceiverNode);
7112 if (rlist) {
7113 List to_delete;
7114 ListIterator it(*rlist);
7115 Node* n;
7116 while ( (n = (Node*)it.getNext()) ) {
7117 if (EqualString(n->getLabelString(), JAVA_SEQUENCE))
7118 to_delete.appendElement((void*)n);
7119 }
7120
7121 if (to_delete.getSize() > 0)
7122 this->deleteNodes(&to_delete);
7123 delete rlist;
7124 rlist = NUL(List*);
7125 }
7126 //
7127 // Before asking to delete the page, make sure that the page
7128 // exists. Reason: deletePage will delete "Untitled" otherwise.
7129 //
7130 EditorWorkSpace* ews = (EditorWorkSpace*)
7131 this->pageSelector->findDefinition(JAVA_SEQ_PAGE);
7132 if (ews != NUL(EditorWorkSpace*)) {
7133 this->pageSelector->selectPage(ews);
7134 this->deletePage(NUL(char*));
7135 }
7136
7137 rlist = (List*)this->network->makeNamedNodeList("WebOptions");
7138 if (rlist) {
7139 this->deleteNodes(rlist);
7140 delete rlist;
7141 rlist = NUL(List*);
7142 }
7143
7144 rlist = (List*)this->network->makeClassifiedNodeList(ClassImageNode);
7145 if (rlist) {
7146 ListIterator it(*rlist);
7147 ImageNode* n;
7148 while ( (n = (ImageNode*)it.getNext()) )
7149 n->unjavifyNode();
7150 delete rlist;
7151 rlist = NUL(List*);
7152 }
7153
7154 return TRUE;
7155 }
7156
7157 //
7158 // Add the special java page. Then merge in a network.
7159 //
javifyNetwork()7160 boolean EditorWindow::javifyNetwork()
7161 {
7162 //
7163 // We must be able to create an instance of the WebOptions macro
7164 //
7165 NodeDefinition* wopt_nd = (NodeDefinition*)
7166 theNodeDefinitionDictionary->findDefinition("WebOptions");
7167
7168 if (!wopt_nd) {
7169 // try loading web-options
7170 char* macros = "/java/server/dxmacros";
7171 const char* uiroot = theDXApplication->getUIRoot();
7172 char* jxmacros;
7173 fprintf(stderr, "WebOptions macro not in DXMACROS path\n");
7174 fprintf(stderr, "attempting to load from configure-time parameters\n");
7175 if (!uiroot)
7176 uiroot = "/usr/local/dx";
7177 jxmacros=(char*)malloc(strlen(uiroot)+strlen(macros)+2);
7178 strcpy(jxmacros,uiroot);
7179 strcat(jxmacros,macros);
7180 MacroDefinition::LoadMacroDirectories(jxmacros,TRUE,NULL,FALSE);
7181 free(jxmacros);
7182 wopt_nd = (NodeDefinition*) theNodeDefinitionDictionary->findDefinition("WebOptions");
7183 }
7184 if (!wopt_nd) {
7185 ErrorMessage (
7186 "The definition of macro WebOptions is missing.\n"
7187 "Load the macros from /usr/local/dx/java/server/dxmacros.\n"
7188 "Otherwise, this visual program will not function properly\n"
7189 "under control of DXServer.\n");
7190 return FALSE;
7191 }
7192
7193
7194 //
7195 // Open a tmp file and write out sequence.net then read it
7196 // back into a temporary Network.
7197 //
7198 GroupManager *page_mgr = (GroupManager*)
7199 this->network->getGroupManagers()->findDefinition(PAGE_GROUP);
7200 Symbol gmgr_sym = page_mgr->getManagerSymbol();
7201 if (this->pageSelector->findDefinition(JAVA_SEQ_PAGE) == NULL) {
7202 const char* tmpdir = theIBMApplication->getTmpDirectory();
7203 char uniq_file[512];
7204 sprintf (uniq_file, "%s/foo.bar", tmpdir);
7205 char* holder_file = UniqueFilename(uniq_file);
7206 FILE* holder = fopen(holder_file, "w");
7207 sprintf (uniq_file, "%s.net", holder_file);
7208 FILE* uniq_f = fopen(uniq_file, "w");
7209
7210 int ll;
7211 for (ll = 0; EditorWindow::SequenceNet[ll] != NULL; ll += 1)
7212 fprintf (uniq_f, "%s", EditorWindow::SequenceNet[ll]);
7213 fclose(uniq_f);
7214 uniq_f = NUL(FILE*);
7215
7216 //
7217 // Merging in the temporary network puts the nodes into java seqno page.
7218 //
7219 boolean non_java_net = TRUE;
7220 Network* tmpnet = theDXApplication->newNetwork(non_java_net);
7221 ASSERT(tmpnet);
7222 boolean status = tmpnet->readNetwork(uniq_file, NULL, TRUE);
7223 unlink (uniq_file);
7224 fclose(holder);
7225 unlink(holder_file);
7226 delete holder_file;
7227 if (status == FALSE) {
7228 delete tmpnet;
7229 return FALSE;
7230 }
7231
7232 //
7233 // Create a new page group in the network.
7234 // Creating the new group also automatically marks selected nodes as belonging.
7235 //
7236 const char* page_name = JAVA_SEQ_PAGE;
7237 this->deselectAllNodes();
7238 ASSERT(page_mgr->createGroup (page_name, this->network));
7239
7240 //
7241 // Make the new WorkSpace page.
7242 //
7243 EditorWorkSpace *page = (EditorWorkSpace*)this->workSpace->addPage();
7244 ASSERT (this->pageSelector->addDefinition (page_name, page));
7245 PageGroupRecord *grec = (PageGroupRecord*)page_mgr->getGroup (page_name);
7246 grec->setComponents (NUL(UIComponent*), page);
7247 this->workSpace->showWorkSpace(page);
7248 gmgr_sym = page_mgr->getManagerSymbol();
7249
7250 this->network->mergeNetworks(tmpnet, NUL(List*), TRUE);
7251 delete tmpnet;
7252 }
7253
7254 //
7255 // Look for Image tools. For each one, connect 2 transmitters - 1 for
7256 // loop number, the other for sequence number.
7257 //
7258 List* imgs = this->network->makeClassifiedNodeList(ClassImageNode);
7259 if (imgs) {
7260 int x, y;
7261 NodeDefinition *rcvr_nd = (NodeDefinition*)
7262 theNodeDefinitionDictionary->findDefinition("Receiver");
7263 ASSERT(rcvr_nd);
7264
7265 ListIterator it(*imgs);
7266 ImageNode* bn;
7267 while ( (bn = (ImageNode*)it.getNext()) ) {
7268 Node* rcvr = NUL(Node*);
7269 Node* wopt = NUL(Node*);
7270 boolean adding_rcvr = TRUE;
7271 if (bn->isJavified() == FALSE) {
7272 bn->getVpePosition(&x,&y);
7273
7274 List* rlist = this->network->makeClassifiedNodeList(ClassReceiverNode);
7275 if (rlist) {
7276 const char* current_page_name = bn->getGroupName(gmgr_sym);
7277 ListIterator it(*rlist);
7278 Node* n;
7279 while ( (n = (Node*)it.getNext()) ) {
7280 boolean same_page = FALSE;
7281 if (EqualString(JAVA_SEQUENCE, n->getLabelString())) {
7282 const char* page_name = n->getGroupName(gmgr_sym);
7283 if (EqualString(page_name, current_page_name)) {
7284 same_page = TRUE;
7285 rcvr = (ReceiverNode*)n;
7286 }
7287 }
7288 if (same_page) {
7289 adding_rcvr = FALSE;
7290 break;
7291 }
7292 }
7293 delete rlist;
7294 rlist = NUL(List*);
7295 }
7296
7297 if (adding_rcvr) {
7298 rcvr = rcvr_nd->createNewNode(this->network);
7299 this->network->copyGroupInfo(bn, rcvr);
7300 rcvr->setVpePosition (x + 90, MAX(0,y-250));
7301 rcvr->setLabelString (JAVA_SEQUENCE);
7302 } else {
7303 ASSERT(rcvr);
7304 }
7305
7306 wopt = wopt_nd->createNewNode(this->network);
7307 this->network->copyGroupInfo(bn, wopt);
7308
7309 const char* group_name = bn->getGroupName(page_mgr->getManagerSymbol());
7310 EditorWorkSpace* ews =
7311 (EditorWorkSpace*)this->pageSelector->findDefinition(group_name);
7312 if (!ews) {
7313 ews = (EditorWorkSpace*)this->workSpace;
7314 this->workSpace->showWorkSpace(ews);
7315 }
7316
7317 wopt->setVpePosition (x + 40, MAX(0,y-100));
7318
7319 //this->network->addNode(wopt, ews);
7320 this->network->addNode(wopt, NUL(EditorWorkSpace*));
7321 if (adding_rcvr) {
7322 //this->network->addNode(rcvr, ews);
7323 this->network->addNode(rcvr, NUL(EditorWorkSpace*));
7324 }
7325 }
7326 bn->javifyNode(wopt, rcvr);
7327 }
7328 delete imgs;
7329 }
7330
7331 return TRUE;
7332 }
7333
reflowEntireGraph()7334 boolean EditorWindow::reflowEntireGraph()
7335 {
7336 WorkSpace *current_ws = this->workSpace;
7337 int page = this->workSpace->getCurrentPage();
7338 if (page) current_ws = this->workSpace->getElement(page);
7339 if (!this->layout_controller)
7340 this->layout_controller = new GraphLayout(this);
7341 boolean retval = this->layout_controller->entireGraph(
7342 current_ws, this->network->nodeList, this->network->decoratorList);
7343
7344 // This will cause the ui to prompt the user to save. In the past we
7345 // always tried to avoid this prompt if repositioning of standIns was
7346 // the only change. We'll see if this is nice.
7347 if (retval) this->network->setFileDirty();
7348 return retval;
7349 }
7350
7351 //
7352 // ewsc can be a StandIn or a VPEAnnotation. A callback from the workspace
7353 // widget has told us that the component has been moved. We fetch its
7354 // location (which is still the old location) and save it so that it can
7355 // be undone.
7356 //
saveLocationForUndo(UIComponent * uic,boolean mouse,boolean same_event)7357 void EditorWindow::saveLocationForUndo (UIComponent* uic, boolean mouse, boolean same_event)
7358 {
7359 boolean separator_pushed = same_event||this->moving_many_standins;
7360 if (this->performing_undo) return ;
7361
7362 boolean found_it = FALSE;
7363 if ((TRUE)||(mouse)||(this->moving_many_standins)) {
7364 ASSERT(uic);
7365 ListIterator iterator;
7366 Node* n;
7367 FOR_EACH_NETWORK_NODE(this->network, n, iterator) {
7368 if (n->getStandIn() == uic) {
7369 StandIn* si = (StandIn*)uic;
7370
7371 // error check
7372 // can't do this error check because something that affects
7373 // a standIn's label can cause bumper cars even if those
7374 // standIns aren't in the current page
7375 //WorkSpace *current_ws = this->workSpace;
7376 //int page = this->workSpace->getCurrentPage();
7377 //if (page) current_ws = this->workSpace->getElement(page);
7378 //ASSERT (current_ws == si->getWorkSpace());
7379
7380 if (!separator_pushed) {
7381 this->undo_list.push(new UndoSeparator(this));
7382 separator_pushed = TRUE;
7383 }
7384
7385 this->undo_list.push ( new UndoStandInMove (
7386 this, si, n->getNameString(), n->getInstanceNumber()
7387 )
7388 );
7389 found_it = TRUE;
7390 break;
7391 }
7392 }
7393 Decorator* dec;
7394 FOR_EACH_NETWORK_DECORATOR(this->network, dec, iterator) {
7395 if (dec == uic) {
7396
7397 if (!separator_pushed) {
7398 this->undo_list.push(new UndoSeparator(this));
7399 separator_pushed = TRUE;
7400 }
7401
7402 this->undo_list.push (new UndoDecoratorMove (this, (VPEAnnotator*)dec));
7403 found_it = TRUE;
7404 break;
7405 }
7406 }
7407 // don't do this because if you drop one thing on top of
7408 // another, someone might unmanage a widget which means
7409 // we'll not be able to find out what happened.
7410 //ASSERT(found_it);
7411 }
7412
7413 // this->setCommandActivation() doesn't run often enough to deal
7414 // with accelerators.
7415 if ((found_it) && (!this->undoCmd->isActive()))
7416 this->setUndoActivation();
7417 }
7418
clearUndoList()7419 void EditorWindow::clearUndoList()
7420 {
7421 if (this->undo_list.getSize() == 0) return;
7422 UndoableAction* undoable;
7423 while ((undoable=(UndoableAction*)this->undo_list.pop()))
7424 delete undoable;
7425 this->undo_list.clear();
7426 this->setUndoActivation();
7427 }
7428
beginMultipleCanvasMovements()7429 void EditorWindow::beginMultipleCanvasMovements()
7430 {
7431 this->moving_many_standins = TRUE;
7432 this->undo_list.push(new UndoSeparator(this));
7433 }
7434
undo()7435 boolean EditorWindow::undo()
7436 {
7437 boolean many_placements = TRUE;//(this->undo_list.getSize() >= 2);
7438 WorkSpace *current_ws = this->workSpace;
7439 if (many_placements) {
7440 int page = this->workSpace->getCurrentPage();
7441 if (page) current_ws = this->workSpace->getElement(page);
7442 current_ws->beginManyPlacements();
7443 }
7444 this->performing_undo = TRUE;
7445 UndoableAction* undoable;
7446
7447 Stack short_stack;
7448 List undo_candidates;
7449 ListIterator iter;
7450 const char* couldnt_undo = NUL(const char*);
7451 int count = 0;
7452 while ((undoable=(UndoableAction*)this->undo_list.pop())) {
7453 if (undoable->isSeparator()) break;
7454 undoable->prepare();
7455 undo_candidates.appendElement(undoable);
7456 count++;
7457 }
7458 for (int i=count; i>=1; i--) {
7459 undoable = (UndoableAction*)undo_candidates.getElement(i);
7460 if (undoable->canUndo()) {
7461 short_stack.push(undoable);
7462 } else {
7463 couldnt_undo = undoable->getLabel();
7464 }
7465 }
7466
7467
7468 if (couldnt_undo) {
7469 if (short_stack.getSize() == 0) {
7470 WarningMessage( "An operation could not be undone: %s", couldnt_undo);
7471 } else {
7472 ErrorMessage ("Part of the operation could not be undone: %s", couldnt_undo);
7473 }
7474 }
7475
7476 boolean first_in_list = TRUE;
7477 while ((undoable=(UndoableAction*)short_stack.pop())) {
7478 undoable->undo(first_in_list);
7479 first_in_list = FALSE;
7480 }
7481
7482 iter.setList(undo_candidates);
7483 while (undoable = (UndoableAction*)iter.getNext()) {
7484 undoable->postpare();
7485 }
7486
7487 this->performing_undo = FALSE;
7488 if (many_placements) {
7489 current_ws->endManyPlacements();
7490 }
7491
7492 this->setUndoActivation();
7493
7494 return TRUE;
7495 }
7496
setUndoActivation()7497 void EditorWindow::setUndoActivation()
7498 {
7499 //if (this->deferrableCommandActivation->isActionDeferred()) return ;
7500
7501 // These 2 numbers work like the float on your sump pump. When
7502 // the level gets really high (up to check_when) the pump runs
7503 // and gets rid of material until it's low (down to max_stack_prune).
7504 // how many individual events are we going to keep around?
7505 int max_stack_prune = 10;
7506 // how big does the stack get before we check it for pruning.
7507 int check_when = 30;
7508
7509 // set up for subsequent undo
7510 char button_label[64];
7511 strcpy (button_label, "Undo");
7512 int current_size = this->undo_list.getSize();
7513 if (current_size > 0) {
7514
7515 UndoableAction* undoable;
7516 if (current_size >= check_when) {
7517 int saved = 0;
7518 Stack tmpStack;
7519 while ((undoable=(UndoableAction*)this->undo_list.pop())) {
7520 if (undoable->isSeparator()) {
7521 saved++;
7522 tmpStack.push(undoable);
7523 } else if (saved < max_stack_prune) {
7524 tmpStack.push(undoable);
7525 } else {
7526 break;
7527 }
7528 }
7529 while ((undoable=(UndoableAction*)this->undo_list.pop()))
7530 delete undoable;
7531
7532 while(undoable = (UndoableAction*)tmpStack.pop()) {
7533 this->undo_list.push(undoable);
7534 }
7535 }
7536
7537 undoable = (UndoableAction*)this->undo_list.peek();
7538 const char* cp = undoable->getLabel();
7539 strcat (button_label, " ");
7540 strcat (button_label, cp);
7541 this->undoCmd->activate();
7542 } else {
7543 this->undoCmd->deactivate();
7544 }
7545 XmString xmstr = XmStringCreateLtoR (button_label, "bold");
7546 XtVaSetValues (this->undoOption->getRootWidget(), XmNlabelString, xmstr, NULL);
7547 XmStringFree(xmstr);
7548 }
7549
KeyHandler(XEvent * event,void * clientData)7550 boolean EditorWindow::KeyHandler(XEvent *event, void *clientData)
7551 {
7552 EditorWindow *ew = (EditorWindow*)clientData;
7553 return ew->keyHandler(event);
7554 }
7555
7556 #if !defined(XK_MISCELLANY)
7557 #define XK_MISCELLANY
7558 #endif
7559 #include <X11/keysym.h>
keyHandler(XEvent * event)7560 boolean EditorWindow::keyHandler(XEvent* event)
7561 {
7562 if (event->type != KeyPress) return TRUE;
7563
7564 KeySym lookedup = XLookupKeysym(((XKeyEvent*)event), 0);
7565 if ((lookedup!=XK_End) && (lookedup!=XK_Page_Up) && (lookedup!=XK_Page_Down))
7566 return TRUE;
7567
7568 Widget ww = XtWindowToWidget(XtDisplay(this->getRootWidget()), event->xany.window);
7569 boolean is_descendant = FALSE;
7570 //
7571 // Choice of window is significant. By using workArea, we're grabbing any
7572 // event that is in the vpe or tool selector. I thought it would be OK
7573 // to get only the events inside the scrolledWindow however, the tool selector
7574 // crashes when given pg-up/pg-down also. It would be nice if there were
7575 // a better way of computing ancestory.
7576 //
7577 // Window win = XtWindow(this->scrolledWindow);
7578 //
7579 Window win = XtWindow(this->workArea);
7580 while ((ww) && (!XtIsShell(ww))) {
7581 if (XtWindow(ww) == win) {
7582 is_descendant = TRUE;
7583 break;
7584 }
7585 ww = XtParent(ww);
7586 }
7587 if (!is_descendant) return TRUE;
7588
7589 XmScrolledWindowWidget scrollWindow;
7590 int xsize,xdelta,xpdelta,x;
7591 int ysize,ydelta,ypdelta,y;
7592
7593 //
7594 // Here, it would be nice to fetch the vertical scrollbar's max value
7595 // and use that in the XK_End calculation, but that causes a core dump
7596 // inside Motif the same way Page-Up/Page-Down do.
7597 //
7598 //int max;
7599 //XtVaGetValues ((Widget)scrollWindow->swindow.vScrollBar, XmNmaximum, &max, NULL);
7600
7601 scrollWindow = (XmScrolledWindowWidget)this->getScrolledWindow();
7602 XmScrollBarGetValues((Widget)scrollWindow->swindow.hScrollBar,
7603 &x, &xsize, &xdelta, &xpdelta);
7604 XmScrollBarGetValues((Widget)scrollWindow->swindow.vScrollBar,
7605 &y, &ysize, &ydelta, &ypdelta);
7606 if (lookedup == XK_Page_Up) {
7607 y-=ypdelta;
7608 y=MAX(y,0);
7609 } else if (lookedup == XK_Page_Down) {
7610 y+=ypdelta;
7611 } else if (lookedup == XK_End) {
7612 //y = max-(ysize+1);
7613 y+=2*ypdelta;
7614 }
7615 this->moveWorkspaceWindow(x,y,FALSE);
7616 return FALSE;
7617 }
7618
saveAllLocationsForUndo(UndoableAction * gridding)7619 void EditorWindow::saveAllLocationsForUndo (UndoableAction* gridding)
7620 {
7621 this->undo_list.push(new UndoSeparator(this));
7622 Node* n;
7623 ListIterator iterator;
7624 FOR_EACH_NETWORK_NODE(this->network, n, iterator) {
7625 StandIn* si = n->getStandIn();
7626 if (!si) continue;
7627
7628 this->undo_list.push ( new UndoStandInMove (
7629 this, si, n->getNameString(), n->getInstanceNumber()
7630 )
7631 );
7632 }
7633
7634 Decorator* dec;
7635 FOR_EACH_NETWORK_DECORATOR(this->network, dec, iterator) {
7636 if (dec->getRootWidget())
7637 this->undo_list.push (new UndoDecoratorMove (this, (VPEAnnotator*)dec));
7638 }
7639 this->undo_list.push(gridding);
7640
7641 // this->setCommandActivation() doesn't run often enough to deal
7642 // with accelerators.
7643 if (!this->undoCmd->isActive())
7644 this->setUndoActivation();
7645 }
7646