~ubuntu-branches/ubuntu/intrepid/tcm/intrepid

« back to all changes in this revision

Viewing changes to src/ed/drawingarea.c

  • Committer: Bazaar Package Importer
  • Author(s): Otavio Salvador
  • Date: 2003-07-03 20:08:21 UTC
  • Revision ID: james.westby@ubuntu.com-20030703200821-se4xtqx25e5miczi
Tags: upstream-2.20
ImportĀ upstreamĀ versionĀ 2.20

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
////////////////////////////////////////////////////////////////////////////////
 
2
//
 
3
// This file is part of Toolkit for Conceptual Modeling (TCM).
 
4
// (c) copyright 1995, Vrije Universiteit Amsterdam.
 
5
// Author: Frank Dehne (frank@cs.vu.nl).
 
6
//
 
7
// TCM is free software; you can redistribute it and/or modify
 
8
// it under the terms of the GNU General Public License as published by
 
9
// the Free Software Foundation; either version 2 of the License, or
 
10
// (at your option) any later version.
 
11
//
 
12
// TCM is distributed in the hope that it will be useful,
 
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
// GNU General Public License for more details.
 
16
//
 
17
// You should have received a copy of the GNU General Public License
 
18
// along with TCM; if not, write to the Free Software
 
19
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
20
// 02111-1307, USA.
 
21
////////////////////////////////////////////////////////////////////////////////
 
22
#include "drawingarea.h"
 
23
#include "viewer.h"
 
24
#include "xgrafport.h"
 
25
#include "messagedialog.h"
 
26
#include "command.h"
 
27
#include "menu.h"
 
28
#include "mstring.h"
 
29
#include "key.h"
 
30
#include "config.h"
 
31
#include <stdlib.h>
 
32
#include <Xm/XmAll.h>
 
33
#include <X11/keysym.h>
 
34
 
 
35
// the standard translations don't work, actually.
 
36
// These are borrowed from an example program in the Motif distribution.
 
37
char DrawingArea::drawTranslations[] = "#replace\n\
 
38
~s ~m ~a <Key>Return:DrawingAreaInput() ManagerParentActivate()\n\
 
39
<Key>Return:DrawingAreaInput() ManagerGadgetSelect()\n\
 
40
<Key>osfActivate:DrawingAreaInput() ManagerParentActivate()\n\
 
41
<Key>osfCancel:DrawingAreaInput() ManagerParentCancel()\n\
 
42
<Key>osfHelp:DrawingAreaInput() ManagerGadgetHelp()\n\
 
43
<Key>space:DrawingAreaInput() ManagerGadgetSelect()\n\
 
44
<Key>osfSelect:DrawingAreaInput() ManagerGadgetSelect()\n\
 
45
<Key>osfBeginLine:DrawingAreaInput()\n\
 
46
<Key>osfEndLine:DrawingAreaInput()\n\
 
47
<KeyDown>:DrawingAreaInput() ManagerGadgetKeyInput()\n\
 
48
<KeyUp>:DrawingAreaInput()\n\
 
49
<Enter>:DrawingAreaInput()\n\
 
50
<Leave>:DrawingAreaInput()\n\
 
51
<BtnMotion>:DrawingAreaInput() ManagerGadgetButtonMotion()\n\
 
52
<Motion>:DrawingAreaInput() ManagerGadgetButtonMotion()\n\
 
53
<Btn1Down>:DrawingAreaInput() ManagerGadgetArm()\n\
 
54
<Btn1Up>:DrawingAreaInput() ManagerGadgetActivate()\n\
 
55
<Btn2Down>:DrawingAreaInput() ManagerGadgetDrag()\n\
 
56
<BtnDown>:DrawingAreaInput()\n\
 
57
<BtnUp>:DrawingAreaInput()";
 
58
 
 
59
DrawingArea::DrawingArea(Config *config, Widget parent, const char *n, 
 
60
                DrawWindow *w): MWidget(n) {
 
61
        drawwindow = w;
 
62
        beenDragging = False;
 
63
        x = 0; y = 0;
 
64
        viewer = 0;
 
65
        grafport = 0;
 
66
        width = min(drawwindow->initDrawingWidth, drawwindow->maxDrawingWidth);
 
67
        height = min(drawwindow->initDrawingHeight, 
 
68
                        drawwindow->maxDrawingHeight);
 
69
        maxWidth = drawwindow->maxDrawingWidth;
 
70
        maxHeight = drawwindow->maxDrawingHeight;
 
71
        // create a drawing area widget
 
72
        SetWidget(XtVaCreateWidget(
 
73
                GetName()->getstr(), xmDrawingAreaWidgetClass, parent,
 
74
                XmNtranslations, XtParseTranslationTable(drawTranslations),
 
75
                XmNheight, height,
 
76
                XmNwidth, width,
 
77
                XmNresizePolicy, XmNONE, // remain this a fixed size
 
78
                0));
 
79
        // set up destruction handler.
 
80
        InstallDestroyHandler();
 
81
        // convert drawing area back to pixels to get its width and height
 
82
        XtVaSetValues(GetWidget(), XmNunitType, XmPIXELS, 0);
 
83
        XtAddCallback(GetWidget(), XmNexposeCallback, DrawCB, this);
 
84
        XtAddCallback(GetWidget(), XmNresizeCallback, DrawCB, this);
 
85
        XtAddCallback(GetWidget(), XmNinputCallback, DrawCB, this);
 
86
        // create popup menu.
 
87
        CreatePopupMenu(drawwindow->GetTool());
 
88
        XtManageChild(GetWidget());
 
89
        Display *display = GetDisplay();
 
90
        Window window = GetWindow();
 
91
        if (!check(display) || !check(window))
 
92
                return;
 
93
        // create new x grafport object.
 
94
        if (check(config)) {
 
95
                grafport = new XGrafport(display, window, width, height);
 
96
                grafport->SetBackgroundColor(config->GetDrawingBackground());
 
97
                grafport->SetForegroundColor(config->GetDrawingForeground());
 
98
                grafport->ClearArea(0,0,width,height);
 
99
        }
 
100
}
 
101
 
 
102
void DrawingArea::SetViewer(Viewer *v) {
 
103
        viewer = v;
 
104
        if (grafport)
 
105
                grafport->SetFont(viewer->GetDefaultFont());
 
106
}
 
107
 
 
108
Pixel DrawingArea::GetBackgroundColor() {
 
109
        Pixel p;
 
110
        XtVaGetValues(GetWidget(), XmNbackground, &p, 0);
 
111
        return p;
 
112
}
 
113
 
 
114
Pixel DrawingArea::GetForegroundColor() {
 
115
        Pixel p;
 
116
        XtVaGetValues(GetWidget(), XmNforeground, &p, 0);
 
117
        return p;
 
118
}
 
119
 
 
120
void DrawingArea::UpdateSize(int w, int h) {
 
121
        w = min(w, maxWidth);
 
122
        h = min(h, maxHeight);
 
123
        XtVaSetValues(GetWidget(), XmNheight, h, XmNwidth, w, 0);
 
124
        height = h;
 
125
        width = w;
 
126
}
 
127
 
 
128
void DrawingArea::FitDocument(int wd, int ht) {
 
129
        if (wd > maxWidth || ht > maxHeight) { 
 
130
                (new MessageDialog(GetWidget(), MessageDialog::WARNING))->
 
131
                 Show("Warning", 
 
132
                        "The drawing area has reached its maximum size\n"
 
133
                        "Can not display the entire document");
 
134
        }
 
135
        wd = min(wd, maxWidth);
 
136
        ht = min(ht, maxHeight);
 
137
        if (ht > height || wd > width) {
 
138
                wd = max(wd, width);
 
139
                ht = max(ht, height);
 
140
                if (check(grafport))
 
141
                        grafport->UpdateSize(wd, ht);
 
142
                UpdateSize(wd, ht);
 
143
                if (viewer)
 
144
                        viewer->Redraw();
 
145
        }
 
146
}
 
147
 
 
148
void DrawingArea::FitDocument() {
 
149
        if (!check(viewer))
 
150
                return;
 
151
        Point p1, p2;
 
152
        viewer->CalcSizeElements(p1, p2);
 
153
        int wd = int(0.5 + 10.0 + grafport->Zoom(p2.x));
 
154
        int ht = int(0.5 + 10.0 + grafport->Zoom(p2.y));
 
155
        FitDocument(wd, ht);
 
156
}
 
157
 
 
158
void DrawingArea::CreatePopupMenu(int tool) {
 
159
        popupMenu = new Menu(GetWidget(), Menu::POPUP, "Edit", 0, 
 
160
                                drawwindow->GetPopupEditItems());
 
161
//      if (Toolkit::EditorWithoutDuplicates(tool)) {
 
162
//              // make "Duplicate" command insensitive.
 
163
//              Widget w1 = popupMenu->GetMenuItem("Duplicate");
 
164
//              if (w1)
 
165
//                      XtVaSetValues(w1, XmNsensitive, False, 0);
 
166
//      }
 
167
}
 
168
 
 
169
void DrawingArea::DrawCB(Widget, XtPointer clientData, XtPointer callData) {
 
170
        DrawingArea *da = (DrawingArea *)clientData;
 
171
        da->Dispatch(callData);
 
172
}
 
173
 
 
174
void DrawingArea::Dispatch (XtPointer callData) {
 
175
        XmDrawingAreaCallbackStruct *dacs = 
 
176
                        (XmDrawingAreaCallbackStruct *)callData;
 
177
        static int dragButton = 0;
 
178
        switch (dacs->reason) {
 
179
        case XmCR_EXPOSE:
 
180
        case XmCR_RESIZE:
 
181
                Redraw(dacs->event);
 
182
                break;
 
183
        case XmCR_INPUT: {
 
184
                if (!check(viewer))
 
185
                        return;
 
186
                bool pasting = viewer->IsPasting();
 
187
                bool zigZag = viewer->IsZigZag();
 
188
                switch (dacs->event->type) {
 
189
                case ButtonPress: {
 
190
                        XButtonEvent *event = (XButtonEvent *)dacs->event;
 
191
                        x = event->x;
 
192
                        y = event->y;
 
193
                        if (event->button == Button3 && 
 
194
                            !(zigZag || pasting || beenDragging))
 
195
                                PopupMenu(dacs->event); 
 
196
                        beenDragging = False;
 
197
                        break;
 
198
                }
 
199
                case ButtonRelease: {
 
200
                        XButtonEvent *event = (XButtonEvent *)dacs->event;
 
201
                        Command *lastcmd = viewer->GetLastCmd();
 
202
                        x = event->x;
 
203
                        y = event->y;
 
204
                        if (zigZag || pasting) {
 
205
                                if (!lastcmd) 
 
206
                                        return;
 
207
                                if ((zigZag && (event->button != Button2) &&
 
208
                                                !(event->state & ShiftMask)) || 
 
209
                                     pasting && (event->button != Button1)) {
 
210
                                        lastcmd->SayAborted();
 
211
                                        lastcmd->Abort();
 
212
                                }
 
213
                                else {
 
214
                                        lastcmd->TrackMouse(Command::TRACK_UP, 
 
215
                                             &anchorPoint, &previousPoint, 
 
216
                                             &nextPoint);
 
217
                                        anchorPoint = nextPoint;
 
218
                                }
 
219
                        }
 
220
                        else if (beenDragging) {
 
221
                                if (!lastcmd) {
 
222
                                        beenDragging = False;
 
223
                                        dragButton = 0;
 
224
                                        return;
 
225
                                }
 
226
                                lastcmd->TrackMouse(Command::TRACK_RELEASE,
 
227
                                          &anchorPoint, &previousPoint, 
 
228
                                          &nextPoint);
 
229
                                if ((int)event->button == dragButton)
 
230
                                        viewer->ExecuteCommand();
 
231
                        }
 
232
                        else if (dragButton == 0) {
 
233
                                if (event->button == Button1) {
 
234
                                        if (event->state & ShiftMask)
 
235
                                                viewer->Adjust(x, y);
 
236
                                        else
 
237
                                                viewer->Select(x, y);
 
238
                                }
 
239
                                else if (event->button == Button2)
 
240
                                        viewer->Adjust(x, y);
 
241
                        }
 
242
                        else if (dragButton > 0) {
 
243
                                if (!lastcmd) {
 
244
                                        beenDragging = False;
 
245
                                        dragButton = 0;
 
246
                                        return;
 
247
                                }
 
248
                                dragButton = -1;
 
249
                                lastcmd->TrackMouse(Command::TRACK_RELEASE,
 
250
                                        &anchorPoint, &previousPoint, 
 
251
                                        &nextPoint);
 
252
                                lastcmd->SayAborted();
 
253
                                lastcmd->Abort();
 
254
                                return;
 
255
                        }
 
256
                        beenDragging = False;
 
257
                        dragButton = 0;
 
258
                        break;
 
259
                }
 
260
                case MotionNotify: {
 
261
                        XMotionEvent *event = (XMotionEvent *)dacs->event;
 
262
                        if (event->state & 
 
263
                            (Button1MotionMask | Button2MotionMask)) {
 
264
                                int xx = event->x;
 
265
                                int yy = event->y;
 
266
                                if (!beenDragging && abs(xx-x) < 5 && 
 
267
                                    abs(yy-y) < 5 && !zigZag) 
 
268
                                        return;
 
269
                                if (!beenDragging && !zigZag) {
 
270
                                        if (pasting)
 
271
                                                return;
 
272
                                        beenDragging = True;
 
273
                                        anchorPoint.Set(x,y);
 
274
                                        previousPoint = anchorPoint;
 
275
                                        nextPoint = anchorPoint;
 
276
                                        Command *newCmd;
 
277
                                        if (event->state & Button1MotionMask) {
 
278
                                                if (event->state & ShiftMask)
 
279
                                                        newCmd = viewer->Connect(x,y);
 
280
                                                else
 
281
                                                        newCmd = viewer->Drag(x,y);
 
282
                                                dragButton = Button1;
 
283
                                        }
 
284
                                        else {  // button2
 
285
                                                newCmd = viewer->Connect(x,y);
 
286
                                                dragButton = Button2;
 
287
                                        }
 
288
                                        viewer->NewCommand(newCmd);
 
289
                                        if (!newCmd) 
 
290
                                                return;
 
291
                                        newCmd->TrackMouse(
 
292
                                                Command::TRACK_PRESS, 
 
293
                                                &anchorPoint, &previousPoint, 
 
294
                                                &nextPoint);
 
295
                                }
 
296
                                if (beenDragging) {
 
297
                                        nextPoint.Set(event->x, event->y);
 
298
                                        Command *lastcmd = viewer->GetLastCmd();
 
299
                                        if (!lastcmd) 
 
300
                                                return;
 
301
                                        lastcmd->TrackMouse(
 
302
                                                Command::TRACK_DRAG, 
 
303
                                                &anchorPoint, &previousPoint, 
 
304
                                                &nextPoint);
 
305
                                        previousPoint = nextPoint;
 
306
                                }
 
307
                                return;
 
308
                        }
 
309
                        else if (zigZag || pasting) {
 
310
                                nextPoint.Set(event->x, event->y);
 
311
                                Command *lastcmd = viewer->GetLastCmd();
 
312
                                if (lastcmd)
 
313
                                        lastcmd->TrackMouse(Command::TRACK_DRAG,
 
314
                                                &anchorPoint, &previousPoint, 
 
315
                                                &nextPoint);
 
316
                                previousPoint = nextPoint;
 
317
                                return;
 
318
                        }
 
319
                        else
 
320
                                viewer->MovingPointer(event->x, event->y);
 
321
                        break;
 
322
                }
 
323
                case KeyPress: {
 
324
                        XKeyEvent *event = (XKeyEvent *)dacs->event;
 
325
                        XComposeStatus status;
 
326
                        KeySym keysym;
 
327
                        int n = XLookupString(event, buf, 5, &keysym, &status);
 
328
                        if (n == 1) {
 
329
                                // normal ascii character.
 
330
                                viewer->KeyTyped(event->x, event->y, buf[0]);
 
331
                        }
 
332
                        else {
 
333
                                // special character.
 
334
                                int code = MapKeySym(keysym);
 
335
                                if (code != 0)
 
336
                                        viewer->KeyTyped(event->x, event->y,
 
337
                                                        code);
 
338
                        }
 
339
                        break;
 
340
                }
 
341
                // next two don't work ??
 
342
                case EnterNotify: {
 
343
                        error("ENTERING !!!\n");
 
344
                        viewer->Activate();
 
345
                        break;
 
346
                }
 
347
                case LeaveNotify: {
 
348
                        error("LEAVING !!!\n");
 
349
                        viewer->Deactivate();
 
350
                        break;
 
351
                }
 
352
                default:
 
353
                        // do nothing.
 
354
                        break;
 
355
                }}
 
356
        }
 
357
}
 
358
 
 
359
void DrawingArea::Redraw(XEvent *e) {
 
360
        if (!e)
 
361
                return;
 
362
        XExposeEvent *event = (XExposeEvent *)e;
 
363
        if (check(grafport))
 
364
                grafport->Redraw(event->x, event->y, 
 
365
                        event->width, event->height, event->x, event->y);
 
366
}
 
367
 
 
368
void DrawingArea::PopupMenu(XEvent *e) {
 
369
        Widget w = popupMenu->GetWidget();
 
370
        XmMenuPosition(w, (XButtonEvent *)e);
 
371
        XtManageChild(w);
 
372
}
 
373
 
 
374
void DrawingArea::EnableUndo(bool flag) {
 
375
        Widget undoMenuItem = popupMenu->GetMenuItem("Undo");
 
376
        if (undoMenuItem)
 
377
                XtVaSetValues(undoMenuItem, XmNsensitive, flag, 0);
 
378
}
 
379
 
 
380
void DrawingArea::EnableRedo(bool flag) {
 
381
        Widget redoMenuItem = popupMenu->GetMenuItem("Redo");
 
382
        if (redoMenuItem)
 
383
                XtVaSetValues(redoMenuItem, XmNsensitive, flag, 0);
 
384
}
 
385
 
 
386
void DrawingArea::Enable(const char *label, bool flag) {
 
387
        Widget menuItem = popupMenu->GetMenuItem(label);
 
388
        if (menuItem)
 
389
                XtVaSetValues(menuItem, XmNsensitive, flag, 0);
 
390
}
 
391
 
 
392
void DrawingArea::SetUndoName(const char *undoname) {
 
393
        XmString s = CreateXmString(undoname);
 
394
        Widget undoMenuItem = popupMenu->GetMenuItem("Undo");
 
395
        if (undoMenuItem)
 
396
                XtVaSetValues(undoMenuItem, XmNlabelString, s, 0);
 
397
        XmStringFree(s);
 
398
}
 
399
 
 
400
void DrawingArea::SetRedoName(const char *redoname) {
 
401
        XmString s = CreateXmString(redoname);
 
402
        Widget redoMenuItem = popupMenu->GetMenuItem("Redo");
 
403
        if (redoMenuItem)
 
404
                XtVaSetValues(redoMenuItem, XmNlabelString, s, 0);
 
405
        XmStringFree(s);
 
406
}
 
407
 
 
408
int DrawingArea::MapKeySym(KeySym keysym) {
 
409
        switch(keysym) {
 
410
#ifdef XK_Home
 
411
        case XK_Home: return Key::HOME;
 
412
#endif
 
413
#ifdef XK_Left
 
414
        case XK_Left: return Key::LEFT;
 
415
#endif
 
416
#ifdef XK_Up
 
417
        case XK_Up: return Key::UP;
 
418
#endif
 
419
#ifdef XK_Right
 
420
        case XK_Right: return Key::RIGHT;
 
421
#endif
 
422
#ifdef XK_Down
 
423
        case XK_Down: return Key::DOWN;
 
424
#endif
 
425
#ifdef XK_Page_Up
 
426
        case XK_Page_Up: return Key::PAGE_UP;
 
427
#endif
 
428
#ifdef XK_Page_Down
 
429
        case XK_Page_Down: return Key::PAGE_DOWN;
 
430
#endif
 
431
#ifdef XK_End
 
432
        case XK_End: return Key::END;
 
433
#endif
 
434
#ifdef XK_Insert
 
435
        case XK_Insert: return Key::INSERT;
 
436
#endif
 
437
        default: return 0;
 
438
        }
 
439
}