home *** CD-ROM | disk | FTP | other *** search
- /*
- * File: objects.cc
- * Purpose: Object graphics library demo for wxWindows.
- * Defines a canvas which repaints its own graphics objects.
- *
- * wxWindows 1.40
- * Copyright (c) 1993 Artificial Intelligence Applications Institute,
- * The University of Edinburgh
- *
- * Author: Julian Smart
- * Date: 18-4-93
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose is hereby granted without fee, provided
- * that the above copyright notice, author statement and this permission
- * notice appear in all copies of this software and related documentation.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
- * IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL THE ARTIFICIAL INTELLIGENCE APPLICATIONS INSTITUTE OR THE
- * UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF
- * DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
- * THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
- /*
- *
- * This shows how the files graphics.h and graphics.cc can be used
- * to maintain objects on an ObjectCanvas. The OnPaint event is handled
- * automatically, and the OnEvent handler routes messages to specific
- * object handlers, e.g. OnLeftClick. Selection of objects (and resizing)
- * is provided, along with drawing lines/splines between objects, with optional
- * arrows.
- *
- * To test out demo, type 'objects'. Create new objects from the Edit menu.
- * Move objects by dragging with left mouse button. SHIFT-left selects
- * (you can then resize) and deselects. Left click on its own displays the
- * object's ID on the main frame status line.
- *
- * See graphics.h for what other types of objects may be created, and other features
- * of CanvasObjects (e.g. clearing/formatting text, flashing etc.) and ObjectCanvases
- * (e.g. Redrawing).
- */
-
- #include <windows.h> // Included only for using MS C/C++ precompiled headers
- #include "wx.h"
- #include "graphics.h"
- #include "objects.h"
-
- // Declare a frame
- MyFrame *frame = NULL;
- wxMenuBar *menu_bar = NULL;
-
- // This statement initialises the whole application
- MyApp myApp;
-
- // The `main program' equivalent, creating the windows and returning the
- // main frame
- wxFrame *MyApp::OnInit(void)
- {
- // Create the main frame window
- frame = new MyFrame(NULL, "wxWindows Graphics Demo", 0, 0, 400, 400);
-
- // Give it a status line
- frame->CreateStatusLine();
-
- // Give it an icon
- wxIcon *icon = new wxIcon("aiai_icn");
- frame->SetIcon(icon);
-
- // Make a menubar
- wxMenu *file_menu = new wxMenu;
- file_menu->Append(OBJECTS_QUIT, "Quit");
-
- wxMenu *edit_menu = new wxMenu;
- edit_menu->Append(OBJECTS_ELLIPSE, "New Ellipse");
- edit_menu->Append(OBJECTS_RECTANGLE, "New Rectangle");
- edit_menu->Append(OBJECTS_EDIT_TEXT, "Edit Text");
- edit_menu->Append(OBJECTS_CONNECT, "Connect");
- edit_menu->Append(OBJECTS_DELETE, "Delete");
-
- wxMenu *help_menu = new wxMenu;
- help_menu->Append(OBJECTS_ABOUT, "About");
-
- menu_bar = new wxMenuBar;
-
- menu_bar->Append(file_menu, "File");
- menu_bar->Append(edit_menu, "Edit");
- menu_bar->Append(help_menu, "Help");
-
- // Associate the menu bar with the frame
- frame->SetMenuBar(menu_bar);
-
- ObjectCanvas *canvas = new ObjectCanvas(frame, 0, 0, 300, 300);
- frame->canvas = canvas;
- wxCursor *cursor = new wxCursor(wxCURSOR_HAND);
- canvas->SetCursor(cursor);
-
- // Give it scrollbars
- canvas->SetScrollbars(20, 20, 50, 50, 4, 4);
-
- // Remember to initialize the graphics library!
- GraphicsInitialize();
-
- // Centre the main window
- frame->Centre();
- frame->SetStatusText("Shift-left to (de)select, drag left to move");
- frame->Show(TRUE);
-
- // Return the main frame window
- return frame;
- }
-
- // Define my frame constructor
- MyFrame::MyFrame(wxFrame *frame, char *title, int x, int y, int w, int h):
- wxFrame(frame, title, x, y, w, h)
- {
- }
-
- // Intercept menu commands
- void MyFrame::OnMenuCommand(int id)
- {
- switch (id)
- {
- case OBJECTS_QUIT:
- {
- OnClose();
- delete this;
- break;
- }
-
- case OBJECTS_ABOUT:
- {
- (void)wxMessageBox("wxWindows GUI library graphics demo Vsn 1.40\nAuthor: Julian Smart J.Smart@ed.ac.uk\nAIAI (c) 1993", "About Object Graphics Demo");
- break;
- }
- case OBJECTS_RECTANGLE:
- {
- MyRectangle *object = new MyRectangle(80, 60);
-
- // Spot the C++ kludge. It's difficult to have all
- // your derived objects to inherit from a new base
- // (my attempts at multiple inheritance were mostly
- // doomed), but at least we can have this bit of data
- // in common.
- object->SetClientData((wxObject *)OBJECTS_RECTANGLE);
-
- // label is our own member, not a CanvasObject's
- object->label = copystring("Default text");
-
- // Easy to colour the border and background
- object->SetPen(black_pen);
- object->SetBrush(red_brush);
-
- // Add the object to the canvas
- canvas->AddObject(object);
-
- // Format the initial text, centring it in the object
- object->FormatText(object->label);
- // You need to do this to display it
- object->Show(TRUE);
-
- // Move it to an appropriate position
- object->Move(150, 150);
- break;
- }
- case OBJECTS_ELLIPSE:
- {
- MyEllipse *object = new MyEllipse(90, 60);
- object->SetClientData((wxObject *)OBJECTS_ELLIPSE);
-
- object->label = copystring("Default text");
- object->SetPen(black_pen);
- object->SetBrush(cyan_brush);
-
- canvas->AddObject(object);
-
- object->FormatText(object->label);
- object->Show(TRUE);
-
- object->Move(150, 150);
- break;
- }
- case OBJECTS_CONNECT:
- {
- wxNode *node = canvas->object_list->First();
- CanvasObject *first = NULL;
- CanvasObject *second = NULL;
- // Collect a couple of nodes (arbitrary order!)
- while (node)
- {
- CanvasObject *obj = (CanvasObject *)node->Data();
- long client_data = (long)obj->GetClientData();
- if (obj->Selected() && (client_data == OBJECTS_ELLIPSE || client_data == OBJECTS_RECTANGLE))
- {
- if (first)
- second = obj;
- else first = obj;
- }
- node = node->Next();
- }
- if (first && second)
- {
- // Ok, add the line
- MyLine *line_object = new MyLine;
-
- // Yes, you can have more than 2 control points! In which case
- // it becomes a multi-segment line, and very pretty it
- // is too. The same for SplineObjects.
- // Try out the line straightening feature sometime, it's
- // rather good if I say so myself.
- line_object->MakeLineControlPoints(2);
- line_object->SetClientData((wxObject *)OBJECTS_CONNECT);
-
- // Add the connection between first and second
- // (the library knows about such things)
- first->AddLine(line_object, second);
- canvas->AddObject(line_object);
- line_object->Show(TRUE);
-
- // It won't get drawn properly unless you move both
- // connected images
- first->Move(first->GetX(), first->GetY());
- second->Move(second->GetX(), second->GetY());
- canvas->Redraw();
- break;
- }
- break;
- }
- case OBJECTS_DELETE:
- {
- // Slightly subtle. Always delete a node's arcs first.
- // When you've deleted a selected image, go to the start of
- // the object list, or you'll be accessing dead objects.
- wxNode *node = canvas->object_list->First();
- while (node)
- {
- CanvasObject *image = (CanvasObject *)node->Data();
- long client_data = (long)image->GetClientData();
- if (image->Selected())
- {
- image->Select(FALSE);
- image->Erase();
-
- switch (client_data)
- {
- case OBJECTS_ELLIPSE:
- case OBJECTS_RECTANGLE:
- {
- wxNode *node1 = image->lines.First();
- while (node1)
- {
- LineObject *line_object = (LineObject *)node1->Data();
- line_object->Erase();
- line_object->Unlink();
- delete line_object;
- node1 = image->lines.First();
- }
- delete image;
- break;
- }
- case OBJECTS_CONNECT:
- {
- LineObject *line_object = (LineObject *)image;
- line_object->Erase();
- line_object->Unlink();
- delete line_object;
- break;
- }
- }
-
- node = canvas->object_list->First();
- } else node = node->Next();
- }
-
- canvas->Redraw();
- break;
- }
-
- case OBJECTS_EDIT_TEXT:
- {
- wxNode *node = canvas->object_list->First();
- while (node)
- {
- CanvasObject *image = (CanvasObject *)node->Data();
- long client_data = (long)image->GetClientData();
- if (image->Selected())
- {
- image->Select(FALSE);
- switch (client_data)
- {
- case OBJECTS_RECTANGLE:
- {
- MyRectangle *object = (MyRectangle *)image;
- char *s = wxGetTextFromUser("Edit text", "Edit", object->label);
- if (s)
- {
- delete object->label;
- object->label = copystring(s);
- object->FormatText(s);
- object->Draw();
- }
- break;
- }
- case OBJECTS_ELLIPSE:
- {
- MyEllipse *object = (MyEllipse *)image;
- char *s = wxGetTextFromUser("Edit text", "Edit", object->label);
- if (s)
- {
- delete object->label;
- object->label = copystring(s);
- object->FormatText(s);
- object->Draw();
- }
- break;
- }
- }
- return;
- }
- node = node->Next();
- }
- break;
- }
- }
- }
-
- // Define the behaviour for the frame closing
- // - must delete all frames except for the main one.
- Bool MyFrame::OnClose(void)
- {
- return TRUE;
- }
-
- void GenericOk(wxButton& but, wxEvent& event)
- {
- wxDialogBox *dialog = (wxDialogBox *)but.GetParent();
-
- dialog->Show(FALSE);
- }
-
- MyRectangle::MyRectangle(float width, float height):RectangleObject(width, height)
- {
- SetPen(black_pen);
- SetBrush(green_brush);
- SetFont(swiss_font_10);
- }
-
- void MyRectangle::OnLeftClick(float x, float y, int keys, int attachment)
- {
- if (keys & KEY_SHIFT)
- {
- // Selection is a concept the library knows about
- if (Selected())
- {
- Select(FALSE);
- canvas->Redraw(); // Redraw because bits of objects will be are missing
- }
- else
- {
- Select(TRUE);
- }
- }
- else if (keys & KEY_CTRL)
- {
- // Do something for CONTROL
- }
- else
- {
- frame->SetStatusText(label);
- }
- }
-
- MyEllipse::MyEllipse(float width, float height):EllipseObject(width, height)
- {
- SetPen(black_pen);
- SetBrush(green_brush);
- SetFont(swiss_font_10);
- }
-
- void MyEllipse::OnLeftClick(float x, float y, int keys, int attachment)
- {
- if (keys & KEY_SHIFT)
- {
- // Selection is a concept the library knows about
- if (Selected())
- {
- Select(FALSE);
- canvas->Redraw(); // Redraw because bits of objects will be are missing
- }
- else
- {
- Select(TRUE);
- }
- }
- else if (keys & KEY_CTRL)
- {
- // Do something for CONTROL
- }
- else
- {
- frame->SetStatusText(label);
- }
- }
-
- MyLine::MyLine(void)
- {
- SetPen(black_pen);
- SetBrush(black_brush);
- SetArrowSize(10, 4);
- SetEndArrow(ARROW_ONE);
- }
-
- void MyLine::OnLeftClick(float x, float y, int keys, int attachment)
- {
- // If more than one link for this item, choose a link
- if (keys & KEY_SHIFT)
- {
- if (Selected())
- {
- Select(FALSE);
- canvas->Redraw(); // Redraw because bits of objects will be are missing
- }
- else
- {
- Select(TRUE);
- }
- }
- else if (keys & KEY_CTRL)
- {
- // Do something for CONTROL
- }
- }
-