home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / code / wxwin140 / samples / objects / objects.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  11.9 KB  |  438 lines

  1. /*
  2.  * File:     objects.cc
  3.  * Purpose:  Object graphics library demo for wxWindows.
  4.  *           Defines a canvas which repaints its own graphics objects.
  5.  *
  6.  *                       wxWindows 1.40
  7.  * Copyright (c) 1993 Artificial Intelligence Applications Institute,
  8.  *                   The University of Edinburgh
  9.  *
  10.  *                     Author: Julian Smart
  11.  *                        Date: 18-4-93
  12.  *
  13.  * Permission to use, copy, modify, and distribute this software and its
  14.  * documentation for any purpose is hereby granted without fee, provided
  15.  * that the above copyright notice, author statement and this permission
  16.  * notice appear in all copies of this software and related documentation.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
  19.  * IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
  20.  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  21.  *
  22.  * IN NO EVENT SHALL THE ARTIFICIAL INTELLIGENCE APPLICATIONS INSTITUTE OR THE
  23.  * UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR
  24.  * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM
  25.  * LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF
  26.  * DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
  27.  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
  28.  *
  29.  */
  30. /*
  31.  *
  32.  * This shows how the files graphics.h and graphics.cc can be used
  33.  * to maintain objects on an ObjectCanvas. The OnPaint event is handled
  34.  * automatically, and the OnEvent handler routes messages to specific
  35.  * object handlers, e.g. OnLeftClick. Selection of objects (and resizing)
  36.  * is provided, along with drawing lines/splines between objects, with optional 
  37.  * arrows.
  38.  *
  39.  * To test out demo, type 'objects'. Create new objects from the Edit menu.
  40.  * Move objects by dragging with left mouse button. SHIFT-left selects
  41.  * (you can then resize) and deselects. Left click on its own displays the
  42.  * object's ID on the main frame status line.
  43.  *
  44.  * See graphics.h for what other types of objects may be created, and other features
  45.  * of CanvasObjects (e.g. clearing/formatting text, flashing etc.) and ObjectCanvases
  46.  * (e.g. Redrawing).
  47.  */
  48.  
  49. #include <windows.h> // Included only for using MS C/C++ precompiled headers
  50. #include "wx.h"
  51. #include "graphics.h"
  52. #include "objects.h"
  53.  
  54. // Declare a frame
  55. MyFrame   *frame = NULL;
  56. wxMenuBar *menu_bar = NULL;
  57.  
  58. // This statement initialises the whole application
  59. MyApp     myApp;
  60.  
  61. // The `main program' equivalent, creating the windows and returning the
  62. // main frame
  63. wxFrame *MyApp::OnInit(void)
  64. {
  65.   // Create the main frame window
  66.   frame = new MyFrame(NULL, "wxWindows Graphics Demo", 0, 0, 400, 400);
  67.  
  68.   // Give it a status line
  69.   frame->CreateStatusLine();
  70.  
  71.   // Give it an icon
  72.   wxIcon *icon = new wxIcon("aiai_icn");
  73.   frame->SetIcon(icon);
  74.  
  75.   // Make a menubar
  76.   wxMenu *file_menu = new wxMenu;
  77.   file_menu->Append(OBJECTS_QUIT, "Quit");
  78.  
  79.   wxMenu *edit_menu = new wxMenu;
  80.   edit_menu->Append(OBJECTS_ELLIPSE, "New Ellipse");
  81.   edit_menu->Append(OBJECTS_RECTANGLE, "New Rectangle");
  82.   edit_menu->Append(OBJECTS_EDIT_TEXT, "Edit Text");
  83.   edit_menu->Append(OBJECTS_CONNECT, "Connect");
  84.   edit_menu->Append(OBJECTS_DELETE, "Delete");
  85.  
  86.   wxMenu *help_menu = new wxMenu;
  87.   help_menu->Append(OBJECTS_ABOUT, "About");
  88.  
  89.   menu_bar = new wxMenuBar;
  90.  
  91.   menu_bar->Append(file_menu, "File");
  92.   menu_bar->Append(edit_menu, "Edit");
  93.   menu_bar->Append(help_menu, "Help");
  94.  
  95.   // Associate the menu bar with the frame
  96.   frame->SetMenuBar(menu_bar);
  97.  
  98.   ObjectCanvas *canvas = new ObjectCanvas(frame, 0, 0, 300, 300);
  99.   frame->canvas = canvas;
  100.   wxCursor *cursor = new wxCursor(wxCURSOR_HAND);
  101.   canvas->SetCursor(cursor);
  102.  
  103.   // Give it scrollbars
  104.   canvas->SetScrollbars(20, 20, 50, 50, 4, 4);
  105.  
  106.   // Remember to initialize the graphics library!
  107.   GraphicsInitialize();
  108.  
  109.   // Centre the main window
  110.   frame->Centre();
  111.   frame->SetStatusText("Shift-left to (de)select, drag left to move");
  112.   frame->Show(TRUE);
  113.  
  114.   // Return the main frame window
  115.   return frame;
  116. }
  117.  
  118. // Define my frame constructor
  119. MyFrame::MyFrame(wxFrame *frame, char *title, int x, int y, int w, int h):
  120.   wxFrame(frame, title, x, y, w, h)
  121. {
  122. }
  123.  
  124. // Intercept menu commands
  125. void MyFrame::OnMenuCommand(int id)
  126. {
  127.   switch (id)
  128.   {
  129.     case OBJECTS_QUIT:
  130.     {
  131.       OnClose();
  132.       delete this;
  133.       break;
  134.     }
  135.  
  136.     case OBJECTS_ABOUT:
  137.     {
  138.       (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");
  139.       break;
  140.     }
  141.     case OBJECTS_RECTANGLE:
  142.     {
  143.       MyRectangle *object = new MyRectangle(80, 60);
  144.  
  145.       // Spot the C++ kludge. It's difficult to have all
  146.       // your derived objects to inherit from a new base
  147.       // (my attempts at multiple inheritance were mostly 
  148.       // doomed), but at least we can have this bit of data
  149.       // in common.
  150.       object->SetClientData((wxObject *)OBJECTS_RECTANGLE);
  151.  
  152.       // label is our own member, not a CanvasObject's
  153.       object->label = copystring("Default text");
  154.  
  155.       // Easy to colour the border and background
  156.       object->SetPen(black_pen);
  157.       object->SetBrush(red_brush);
  158.  
  159.       // Add the object to the canvas
  160.       canvas->AddObject(object);
  161.  
  162.       // Format the initial text, centring it in the object
  163.       object->FormatText(object->label);
  164.       // You need to do this to display it
  165.       object->Show(TRUE);
  166.  
  167.       // Move it to an appropriate position
  168.       object->Move(150, 150);
  169.       break;
  170.     }
  171.     case OBJECTS_ELLIPSE:
  172.     {
  173.       MyEllipse *object = new MyEllipse(90, 60);
  174.       object->SetClientData((wxObject *)OBJECTS_ELLIPSE);
  175.  
  176.       object->label = copystring("Default text");
  177.       object->SetPen(black_pen);
  178.       object->SetBrush(cyan_brush);
  179.  
  180.       canvas->AddObject(object);
  181.  
  182.       object->FormatText(object->label);
  183.       object->Show(TRUE);
  184.  
  185.       object->Move(150, 150);
  186.       break;
  187.     }
  188.     case OBJECTS_CONNECT:
  189.     {
  190.       wxNode *node = canvas->object_list->First();
  191.       CanvasObject *first = NULL;
  192.       CanvasObject *second = NULL;
  193.       // Collect a couple of nodes (arbitrary order!)
  194.       while (node)
  195.       {
  196.         CanvasObject *obj = (CanvasObject *)node->Data();
  197.         long client_data = (long)obj->GetClientData();
  198.         if (obj->Selected() && (client_data == OBJECTS_ELLIPSE || client_data == OBJECTS_RECTANGLE))
  199.     {
  200.           if (first)
  201.             second = obj;
  202.           else first = obj;
  203.     }
  204.         node = node->Next();
  205.       }
  206.       if (first && second)
  207.       {
  208.         // Ok, add the line
  209.         MyLine *line_object = new MyLine;
  210.  
  211.         // Yes, you can have more than 2 control points! In which case
  212.         // it becomes a multi-segment line, and very pretty it
  213.         // is too. The same for SplineObjects.
  214.         // Try out the line straightening feature sometime, it's
  215.         // rather good if I say so myself.
  216.         line_object->MakeLineControlPoints(2);
  217.         line_object->SetClientData((wxObject *)OBJECTS_CONNECT);
  218.  
  219.         // Add the connection between first and second
  220.         // (the library knows about such things)
  221.         first->AddLine(line_object, second);
  222.         canvas->AddObject(line_object);
  223.         line_object->Show(TRUE);
  224.  
  225.         // It won't get drawn properly unless you move both
  226.         // connected images
  227.         first->Move(first->GetX(), first->GetY());
  228.         second->Move(second->GetX(), second->GetY());
  229.         canvas->Redraw();
  230.         break;
  231.       }
  232.       break;
  233.     }
  234.     case OBJECTS_DELETE:
  235.     {
  236.       // Slightly subtle. Always delete a node's arcs first.
  237.       // When you've deleted a selected image, go to the start of
  238.       // the object list, or you'll be accessing dead objects.
  239.       wxNode *node = canvas->object_list->First();
  240.       while (node)
  241.       {
  242.         CanvasObject *image = (CanvasObject *)node->Data();
  243.         long client_data = (long)image->GetClientData();
  244.         if (image->Selected())
  245.         {
  246.           image->Select(FALSE);
  247.           image->Erase();
  248.  
  249.           switch (client_data)
  250.       {
  251.             case OBJECTS_ELLIPSE:
  252.             case OBJECTS_RECTANGLE:
  253.             {
  254.               wxNode *node1 = image->lines.First();
  255.               while (node1)
  256.           {
  257.                 LineObject *line_object = (LineObject *)node1->Data();
  258.                 line_object->Erase();
  259.                 line_object->Unlink();
  260.                 delete line_object;
  261.                 node1 = image->lines.First();
  262.           }
  263.               delete image;
  264.               break;
  265.             }
  266.             case OBJECTS_CONNECT:
  267.         {
  268.               LineObject *line_object = (LineObject *)image;
  269.               line_object->Erase();
  270.               line_object->Unlink();
  271.               delete line_object;
  272.               break;
  273.         }
  274.       }
  275.  
  276.           node = canvas->object_list->First();
  277.         } else node = node->Next();
  278.       }
  279.  
  280.       canvas->Redraw();
  281.       break;
  282.     }
  283.  
  284.     case OBJECTS_EDIT_TEXT:
  285.     {
  286.       wxNode *node = canvas->object_list->First();
  287.       while (node)
  288.       {
  289.         CanvasObject *image = (CanvasObject *)node->Data();
  290.         long client_data = (long)image->GetClientData();
  291.         if (image->Selected())
  292.         {
  293.           image->Select(FALSE);
  294.           switch (client_data)
  295.       {
  296.             case OBJECTS_RECTANGLE:
  297.         {
  298.               MyRectangle *object = (MyRectangle *)image;
  299.               char *s = wxGetTextFromUser("Edit text", "Edit", object->label);
  300.               if (s)
  301.           {
  302.                 delete object->label;
  303.                 object->label = copystring(s);
  304.                 object->FormatText(s);
  305.                 object->Draw();
  306.           }
  307.               break;
  308.         }
  309.             case OBJECTS_ELLIPSE:
  310.         {
  311.               MyEllipse *object = (MyEllipse *)image;
  312.               char *s = wxGetTextFromUser("Edit text", "Edit", object->label);
  313.               if (s)
  314.           {
  315.                 delete object->label;
  316.                 object->label = copystring(s);
  317.                 object->FormatText(s);
  318.                 object->Draw();
  319.           }
  320.               break;
  321.         }
  322.       }
  323.           return;
  324.     }
  325.         node = node->Next();
  326.       }
  327.       break;
  328.     }
  329.   }
  330. }
  331.  
  332. // Define the behaviour for the frame closing
  333. // - must delete all frames except for the main one.
  334. Bool MyFrame::OnClose(void)
  335. {
  336.   return TRUE;
  337. }
  338.  
  339. void GenericOk(wxButton& but, wxEvent& event)
  340. {
  341.   wxDialogBox *dialog = (wxDialogBox *)but.GetParent();
  342.  
  343.   dialog->Show(FALSE);
  344. }
  345.  
  346. MyRectangle::MyRectangle(float width, float height):RectangleObject(width, height)
  347. {
  348.   SetPen(black_pen);
  349.   SetBrush(green_brush);
  350.   SetFont(swiss_font_10);
  351. }
  352.  
  353. void MyRectangle::OnLeftClick(float x, float y, int keys, int attachment)
  354. {
  355.   if (keys & KEY_SHIFT)
  356.   {
  357.     // Selection is a concept the library knows about
  358.     if (Selected())
  359.     {
  360.       Select(FALSE);
  361.       canvas->Redraw(); // Redraw because bits of objects will be are missing
  362.     }
  363.     else
  364.     {
  365.       Select(TRUE);
  366.     }
  367.   }
  368.   else if (keys & KEY_CTRL)
  369.   {
  370.     // Do something for CONTROL
  371.   }
  372.   else
  373.   {
  374.     frame->SetStatusText(label);
  375.   }
  376. }
  377.  
  378. MyEllipse::MyEllipse(float width, float height):EllipseObject(width, height)
  379. {
  380.   SetPen(black_pen);
  381.   SetBrush(green_brush);
  382.   SetFont(swiss_font_10);
  383. }
  384.  
  385. void MyEllipse::OnLeftClick(float x, float y, int keys, int attachment)
  386. {
  387.   if (keys & KEY_SHIFT)
  388.   {
  389.     // Selection is a concept the library knows about
  390.     if (Selected())
  391.     {
  392.       Select(FALSE);
  393.       canvas->Redraw(); // Redraw because bits of objects will be are missing
  394.     }
  395.     else
  396.     {
  397.       Select(TRUE);
  398.     }
  399.   }
  400.   else if (keys & KEY_CTRL)
  401.   {
  402.     // Do something for CONTROL
  403.   }
  404.   else
  405.   {
  406.     frame->SetStatusText(label);
  407.   }
  408. }
  409.  
  410. MyLine::MyLine(void)
  411. {
  412.   SetPen(black_pen);
  413.   SetBrush(black_brush);
  414.   SetArrowSize(10, 4);
  415.   SetEndArrow(ARROW_ONE);
  416. }
  417.  
  418. void MyLine::OnLeftClick(float x, float y, int keys, int attachment)
  419. {
  420.   // If more than one link for this item, choose a link
  421.   if (keys & KEY_SHIFT)
  422.   {
  423.     if (Selected())
  424.     {
  425.       Select(FALSE);
  426.       canvas->Redraw(); // Redraw because bits of objects will be are missing
  427.     }
  428.     else
  429.     {
  430.       Select(TRUE);
  431.     }
  432.   }
  433.   else if (keys & KEY_CTRL)
  434.   {
  435.     // Do something for CONTROL
  436.   }
  437. }
  438.