void MyFrame::OnCloseWindow(wxCloseEvent& event)
{
- if (wxDocParentFrame::OnClose())
+ wxDocParentFrame::OnCloseWindow(event);
+ if (!event.GetVeto())
{
wxOGLCleanUp();
- this->Destroy();
}
- else
- event.Veto();
}
// Intercept menu commands
--- /dev/null
+/* XPM */
+static char *alignb_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c Yellow",
+/* pixels */
+" ",
+" ........",
+" .XXXXXX.",
+" .XXXXXX.",
+" .XXXXXX.",
+" .XXXXXX.",
+" .XXXXXX.",
+" ..... .XXXXXX.",
+" .XXX. .XXXXXX.",
+" .XXX. .XXXXXX.",
+" .XXX. .XXXXXX.",
+" .XXX. .XXXXXX.",
+" ..... ........",
+" ",
+" "
+};
--- /dev/null
+/* XPM */
+static char *alignl_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c Yellow",
+/* pixels */
+" ",
+" ...... ",
+" .XXXX. ",
+" .XXXX. ",
+" .XXXX. ",
+" ...... ",
+" ",
+" ",
+" ........... ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" ........... ",
+" "
+};
--- /dev/null
+/* XPM */
+static char *alignr_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c Yellow",
+/* pixels */
+" ",
+" ...... ",
+" .XXXX. ",
+" .XXXX. ",
+" .XXXX. ",
+" ...... ",
+" ",
+" ",
+" ........... ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" ........... ",
+" "
+};
--- /dev/null
+/* XPM */
+static char *alignt_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c Yellow",
+/* pixels */
+" ",
+" ..... ........",
+" .XXX. .XXXXXX.",
+" .XXX. .XXXXXX.",
+" .XXX. .XXXXXX.",
+" .XXX. .XXXXXX.",
+" ..... .XXXXXX.",
+" .XXXXXX.",
+" .XXXXXX.",
+" .XXXXXX.",
+" .XXXXXX.",
+" .XXXXXX.",
+" ........",
+" ",
+" "
+};
--- /dev/null
+/* XPM */
+static char *arrow_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 22 22 2 1",
+/* colors */
+". c #000000",
+"# c #c0c0c0",
+/* pixels */
+"######################",
+"######################",
+"######################",
+"######################",
+"######################",
+"#######.##############",
+"#######..#############",
+"#######...############",
+"#######....###########",
+"#######.....##########",
+"#######......#########",
+"#######.......########",
+"#######........#######",
+"#######.....##########",
+"#######..#..##########",
+"#######.###..#########",
+"###########..#########",
+"############..########",
+"############..########",
+"######################",
+"######################",
+"######################"
+};
--- /dev/null
+/* XPM */
+static char *copy_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 4 1",
+" c None",
+". c Black",
+"X c Gray100",
+"o c #000080",
+/* pixels */
+" ",
+" ...... ",
+" .XXXX.. ",
+" .XXXX.X. ",
+" .X..X.oooooo ",
+" .XXXXXoXXXXoo ",
+" .X....oXXXXoXo ",
+" .XXXXXoX..Xoooo",
+" .X....oXXXXXXXo",
+" .XXXXXoX.....Xo",
+" ......oXXXXXXXo",
+" oX.....Xo",
+" oXXXXXXXo",
+" ooooooooo",
+" "
+};
--- /dev/null
+/* XPM */
+static char *copysize_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c Yellow",
+/* pixels */
+" ",
+".......... ... ",
+".XXXXXXXX. . ",
+".XXXXXXXX. . ",
+".XXXXXXXX. .....",
+".XXXXXXXX. ... ",
+".......... . ",
+" ",
+" . . . . . . ",
+" ",
+" . ...... . ",
+" .XXXX. ",
+" . ...... . ",
+" ",
+" . . . . . . "
+};
--- /dev/null
+/* XPM */
+static char *cut_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c #000080",
+/* pixels */
+" ",
+" . . ",
+" . . ",
+" . . ",
+" .. .. ",
+" . . ",
+" ... ",
+" . ",
+" X.X ",
+" X XXX ",
+" XXX X X ",
+" X X X X ",
+" X X X X ",
+" X X XX ",
+" XX "
+};
--- /dev/null
+/* XPM */
+static char *cutpoint_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 15 3 1",
+/* colors */
+". c #000000",
+"# c #800000",
+"a c #c0c0c0",
+/* pixels */
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aa#aaaaaaaaa#aaa",
+"aaa#aaaaaaa#aaaa",
+"aaaa#aaaaa#aaaaa",
+"aaaaa#...#aaaaaa",
+"aaaaaa#.#.aaaaaa",
+".......#........",
+"aaaaaa#.#.aaaaaa",
+"aaaaa#...#aaaaaa",
+"aaaa#aaaaa#aaaaa",
+"aaa#aaaaaaa#aaaa",
+"aa#aaaaaaaaa#aaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa"
+};
--- /dev/null
+/* XPM */
+static char *help_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c #008080",
+/* pixels */
+" ",
+" ...... ",
+" .XXXXX.. ",
+" .XX...XX.. ",
+" .X.. .X.. ",
+" .X.. .XX.. ",
+" .. .XX.. ",
+" .XX.. ",
+" .X.. ",
+" .X.. ",
+" .X.. ",
+" .. ",
+" .XX.. ",
+" .XX.. ",
+" ... "
+};
--- /dev/null
+/* XPM */
+static char *helpcs_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 15 2 1",
+/* colors */
+". c #000000",
+"# c #c0c0c0",
+/* pixels */
+"################",
+".########.....##",
+"..######..###..#",
+"...####..####...",
+"....###..####...",
+".....###..###..#",
+"......######..##",
+".......####..###",
+"........##..####",
+".....#####..####",
+"..#..###########",
+".###..####...###",
+"####..####...###",
+"#####..#########",
+"#####..#########"
+};
--- /dev/null
+/* XPM */
+static char *horiz_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c Yellow",
+/* pixels */
+" ",
+" ..... ",
+" .XXX. ",
+" .XXX. ",
+" .XXX. ",
+" ..... ",
+" ",
+" ",
+" ........... ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" ........... ",
+" "
+};
--- /dev/null
+/* XPM */
+static char *linearrow_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 15 3 1",
+/* colors */
+". c #000000",
+"# c #800000",
+"a c #c0c0c0",
+/* pixels */
+"aaaaaaaaaaaaaaaa",
+"aaaaa#aaaaaaaaaa",
+"aaaaa##aaaaaaaaa",
+"aaaaa###aaaaaaaa",
+"aaaaa####aaaaaaa",
+"aaaaa#####aaaaaa",
+".....######.....",
+".....######.....",
+"aaaaa#####aaaaaa",
+"aaaaa####aaaaaaa",
+"aaaaa###aaaaaaaa",
+"aaaaa##aaaaaaaaa",
+"aaaaa#aaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa"
+};
--- /dev/null
+/* XPM */
+static char *new_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c Gray100",
+/* pixels */
+" ",
+" ........ ",
+" .XXXXXX.. ",
+" .XXXXXX.X. ",
+" .XXXXXX.... ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" ........... ",
+" "
+};
--- /dev/null
+/* XPM */
+static char *newpoint_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 15 3 1",
+/* colors */
+". c #000000",
+"# c #c0c0c0",
+"a c #ffff00",
+/* pixels */
+"#######a########",
+"###a###a###a####",
+"####a##a##a#####",
+"#####a#a#a######",
+"################",
+"##aaa#....#aaa##",
+"######....######",
+"................",
+"######....######",
+"######....######",
+"################",
+"################",
+"################",
+"################",
+"################"
+};
--- /dev/null
+/* XPM */
+static char *open_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 5 1",
+" c None",
+". c Black",
+"X c Yellow",
+"o c Gray100",
+"O c #bfbf00",
+/* pixels */
+" ",
+" ... ",
+" . . .",
+" ..",
+" ... ...",
+" .XoX....... ",
+" .oXoXoXoXo. ",
+" .XoXoXoXoX. ",
+" .oXoX..........",
+" .XoX.OOOOOOOOO.",
+" .oo.OOOOOOOOO. ",
+" .X.OOOOOOOOO. ",
+" ..OOOOOOOOO. ",
+" ........... ",
+" "
+};
--- /dev/null
+/* XPM */
+static char *paste_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 6 1",
+" c None",
+". c Black",
+"X c Yellow",
+"o c #808080",
+"O c #000080",
+"+ c Gray100",
+/* pixels */
+" ",
+" .... ",
+" .....XX..... ",
+".ooo.X..X.ooo. ",
+".oo. .oo. ",
+".oo........oo. ",
+".oooooooooooo. ",
+".oooooOOOOOOO. ",
+".oooooO+++++OO ",
+".oooooO+++++O+O ",
+".oooooO+OOO+OOO ",
+".oooooO+++++++O ",
+".oooooO+OOOOO+O ",
+" .....O+++++++O ",
+" OOOOOOOOO "
+};
--- /dev/null
+/* XPM */
+static char *preview_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 5 1",
+" c Black",
+". c None",
+"X c Gray100",
+"o c #808080",
+"O c Cyan",
+/* pixels */
+" .......",
+" XXXXXXX ......",
+" XXXXXXX . .....",
+" XXXXXXX ....",
+" XXXXXXXXXX ....",
+" XXXXXXX ....",
+" XXXXXX o..o ...",
+" XXXXX oOO.oo ..",
+" XXXXX .O..o. ..",
+" XXXXX ....o. ..",
+" XXXXX o..Ooo ..",
+" XXXXXX o..o o..",
+" XXXXXXX o .",
+" XXXXXXXXXX . ",
+" .. "
+};
--- /dev/null
+/* XPM */
+static char *print_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 5 1",
+" c None",
+". c Black",
+"X c Gray100",
+"o c #808000",
+"O c Yellow",
+/* pixels */
+" ",
+" ......... ",
+" .XXXXXXXX. ",
+" .X.....X. ",
+" .XXXXXXXX. ",
+" .X.....X.... ",
+" .XXXXXXXX. . .",
+" .......... . ..",
+". . . .",
+"............. .",
+". ooo . . ",
+". OOO ... ",
+"............. . ",
+" . . . ",
+" ........... "
+};
--- /dev/null
+/* XPM */
+static char *redo_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 15 3 1",
+/* colors */
+". c #000080",
+"# c #c0c0c0",
+"a c #808080",
+/* pixels */
+"################",
+"################",
+"################",
+"################",
+"###a....########",
+"##a.####..###.##",
+"##.#######.#..##",
+"##.########...##",
+"##.#######....##",
+"##a.#####.....##",
+"###.a###########",
+"################",
+"################",
+"################",
+"################"
+};
--- /dev/null
+/* XPM */
+static char *save_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 4 1",
+" c None",
+". c Black",
+"X c #808000",
+"o c #808080",
+/* pixels */
+" ",
+" .............. ",
+" .X. . . ",
+" .X. ... ",
+" .X. .X. ",
+" .X. .X. ",
+" .X. .X. ",
+" .X. .X. ",
+" .XX........oX. ",
+" .XXXXXXXXXXXX. ",
+" .XX.........X. ",
+" .XX...... .X. ",
+" .XX...... .X. ",
+" .XX...... .X. ",
+" ............. "
+};
--- /dev/null
+/* XPM */
+static char *straight_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 15 2 1",
+/* colors */
+". c #000000",
+"# c #c0c0c0",
+/* pixels */
+"################",
+".........#######",
+".........#######",
+"#######..#######",
+"#######..#######",
+"#######..#######",
+"#######..#######",
+"#######..#######",
+"#######..#######",
+"#######..#######",
+"#######..#######",
+"#######..#######",
+"#######.........",
+"#######.........",
+"################"
+};
--- /dev/null
+/* XPM */
+static char *texttool_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 22 22 2 1",
+/* colors */
+". c #000000",
+"# c #c0c0c0",
+/* pixels */
+"######################",
+"######################",
+"######################",
+"######################",
+"##########..##########",
+"##########..##########",
+"#########....#########",
+"#########....#########",
+"########.....#########",
+"########..#...########",
+"#######..##...########",
+"#######..###...#######",
+"######.........#######",
+"######..####...#######",
+"######.######...######",
+"#####..######...######",
+"####....####......####",
+"######################",
+"######################",
+"######################",
+"######################",
+"######################"
+};
--- /dev/null
+/* XPM */
+static char *toback_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 4 1",
+" c None",
+". c Black",
+"X c #808080",
+"o c Yellow",
+/* pixels */
+" ....... ",
+" .XXXXX. ",
+" .XXXXX...... ",
+" .XXXXX.oooo. ",
+" .XXXXX.oooo. ",
+" .XXXXX.oooo. ",
+" .......oooo. ",
+" .oooo.......",
+" .oooo.XXXXX.",
+" .oooo.XXXXX.",
+" ......XXXXX.",
+" .XXXXX.",
+" .XXXXX.",
+" .......",
+" "
+};
--- /dev/null
+/* XPM */
+static char *tofront_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 4 1",
+" c None",
+". c Black",
+"X c #808080",
+"o c Yellow",
+/* pixels */
+" ....... ",
+" .XXXXX. ",
+" .XX......... ",
+" .XX.ooooooo. ",
+" .XX.ooooooo. ",
+" .XX.ooooooo. ",
+" ....ooooooo. ",
+" .ooooooo....",
+" .ooooooo.XX.",
+" .ooooooo.XX.",
+" .........XX.",
+" .XXXXX.",
+" .XXXXX.",
+" .......",
+" "
+};
--- /dev/null
+/* XPM */
+static char *undo_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 15 3 1",
+/* colors */
+". c #000080",
+"# c #c0c0c0",
+"a c #808080",
+/* pixels */
+"################",
+"################",
+"################",
+"################",
+"########....a###",
+"##.###..####.a##",
+"##..#.#######.##",
+"##...########.##",
+"##....#######.##",
+"##.....#####.a##",
+"###########a.###",
+"################",
+"################",
+"################",
+"################"
+};
--- /dev/null
+/* XPM */
+static char *vert_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c Yellow",
+/* pixels */
+" ",
+" ........",
+" .XXXXXX.",
+" .XXXXXX.",
+" ..... .XXXXXX.",
+" .XXX. .XXXXXX.",
+" .XXX. .XXXXXX.",
+" .XXX. .XXXXXX.",
+" .XXX. .XXXXXX.",
+" ..... .XXXXXX.",
+" .XXXXXX.",
+" .XXXXXX.",
+" ........",
+" ",
+" "
+};
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: cspalette.cpp
+// Purpose: OGLEdit palette
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+// #pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include <wx/wxprec.h>
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+#include <wx/laywin.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "doc.h"
+#include "view.h"
+#include "studio.h"
+#include "cspalette.h"
+#include "symbols.h"
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__)
+#include "bitmaps/arrow.xpm"
+#include "bitmaps/texttool.xpm"
+#endif
+
+/*
+ * Object editor tool palette
+ *
+ */
+
+csEditorToolPalette::csEditorToolPalette(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
+ long style):
+ TOOLPALETTECLASS(parent, id, pos, size, style)
+{
+ m_currentlySelected = -1;
+
+ SetMaxRowsCols(1, 1000);
+}
+
+bool csEditorToolPalette::OnLeftClick(int toolIndex, bool toggled)
+{
+ // BEGIN mutual exclusivity code
+ if (toggled && (m_currentlySelected != -1) && (toolIndex != m_currentlySelected))
+ ToggleTool(m_currentlySelected, FALSE);
+
+ if (toggled)
+ m_currentlySelected = toolIndex;
+ else if (m_currentlySelected == toolIndex)
+ m_currentlySelected = -1;
+ // END mutual exclusivity code
+
+ return TRUE;
+}
+
+void csEditorToolPalette::OnMouseEnter(int toolIndex)
+{
+ wxString msg("");
+ if (toolIndex == PALETTE_ARROW)
+ msg = "Pointer";
+ else if (toolIndex != -1)
+ {
+ csSymbol* symbol = wxGetApp().GetSymbolDatabase()->FindSymbol(toolIndex);
+ if (symbol)
+ msg = symbol->GetName();
+ }
+ ((wxFrame*) wxGetApp().GetTopWindow())->SetStatusText(msg);
+}
+
+void csEditorToolPalette::SetSize(int x, int y, int width, int height, int sizeFlags)
+{
+ TOOLPALETTECLASS::SetSize(x, y, width, height, sizeFlags);
+}
+
+void csEditorToolPalette::SetSelection(int sel)
+{
+ if ((sel != m_currentlySelected) && (m_currentlySelected != -1))
+ {
+ ToggleTool(m_currentlySelected, FALSE);
+ }
+ m_currentlySelected = sel;
+ ToggleTool(m_currentlySelected, TRUE);
+}
+
+bool csApp::CreatePalette(wxFrame *parent)
+{
+ // First create a layout window
+ wxSashLayoutWindow* win = new wxSashLayoutWindow(parent, ID_LAYOUT_WINDOW_PALETTE, wxDefaultPosition, wxSize(200, 30), wxNO_BORDER|wxSW_3D|wxCLIP_CHILDREN);
+ win->SetDefaultSize(wxSize(10000, 40));
+ win->SetOrientation(wxLAYOUT_HORIZONTAL);
+ win->SetAlignment(wxLAYOUT_TOP);
+ win->SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
+ win->SetSashVisible(wxSASH_BOTTOM, TRUE);
+
+ m_diagramPaletteSashWindow = win;
+
+ m_diagramPaletteSashWindow->Show(FALSE);
+
+ // Load palette bitmaps
+#ifdef __WXMSW__
+ wxBitmap PaletteArrow("arrowtool");
+ wxBitmap TextTool("texttool");
+#elif defined(__WXGTK__) || defined(__WXMOTIF__)
+ wxBitmap PaletteArrow(arrow_xpm);
+ wxBitmap TextTool(texttool_xpm);
+#endif
+
+ csEditorToolPalette *palette = new csEditorToolPalette(m_diagramPaletteSashWindow, ID_DIAGRAM_PALETTE, wxPoint(0, 0), wxSize(-1, -1), wxTB_HORIZONTAL|wxNO_BORDER);
+
+ palette->SetMargins(2, 2);
+
+ palette->SetToolBitmapSize(wxSize(32, 32));
+
+ palette->AddTool(PALETTE_ARROW, PaletteArrow, wxNullBitmap, TRUE, 0, -1, NULL, "Pointer");
+ palette->AddTool(PALETTE_TEXT_TOOL, TextTool, wxNullBitmap, TRUE, 0, -1, NULL, "Text");
+
+ wxNode* node = GetSymbolDatabase()->GetSymbols().First();
+ while (node)
+ {
+ csSymbol* symbol = (csSymbol*) node->Data();
+ wxBitmap* bitmap = GetSymbolDatabase()->CreateToolBitmap(symbol);
+ palette->AddTool(symbol->GetToolId(), *bitmap, wxNullBitmap, TRUE, 0, -1, NULL, symbol->GetName());
+
+ delete bitmap;
+
+ node = node->Next();
+ }
+
+ palette->Realize();
+
+ palette->SetSelection(PALETTE_ARROW);
+ m_diagramPalette = palette;
+
+ return TRUE;
+}
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: cspalette.h
+// Purpose: OGL sample palette
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _STUDIO_CSPALETTE_H_
+#define _STUDIO_CSPALETTE_H_
+
+#ifdef __GNUG__
+// #pragma interface
+#endif
+
+#include <wx/wx.h>
+#include <wx/string.h>
+#include <wx/tbarsmpl.h>
+
+/*
+ * Object editor tool palette
+ *
+ */
+
+// TODO for wxWin: wxToolBar95 cannot be moved to a non-0,0 position!
+// Needs to have a parent window...
+// So use a simple toolbar at present.
+#define TOOLPALETTECLASS wxToolBarSimple
+
+class csEditorToolPalette: public TOOLPALETTECLASS
+{
+public:
+
+ csEditorToolPalette(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = wxTB_VERTICAL);
+
+ bool OnLeftClick(int toolIndex, bool toggled);
+ void OnMouseEnter(int toolIndex);
+
+ inline int GetSelection() const { return m_currentlySelected; }
+ void SetSelection(int sel);
+
+ void SetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
+
+protected:
+ int m_currentlySelected;
+};
+
+#define PALETTE_ARROW 200
+#define PALETTE_TEXT_TOOL 201
+
+#endif
+ // _STUDIO_CSPALETTE_H_
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: csprint.cpp
+// Purpose: Printing and clipboard functionality
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+// #pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include <wx/wxprec.h>
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+#include <wx/wxexpr.h>
+#include <wx/clipbrd.h>
+
+#ifdef __WXMSW__
+#include <wx/metafile.h>
+#endif
+
+#include "studio.h"
+#include "doc.h"
+#include "shapes.h"
+#include "view.h"
+
+IMPLEMENT_DYNAMIC_CLASS(wxDiagramClipboard, wxDiagram)
+
+// Copy selection
+bool wxDiagramClipboard::Copy(wxDiagram* diagram)
+{
+ DeleteAllShapes();
+
+ return DoCopy(diagram, this, FALSE, NULL);
+}
+
+// Copy contents to the diagram, with new ids.
+
+bool wxDiagramClipboard::Paste(wxDiagram* diagram, wxDC* dc, int offsetX, int offsetY)
+{
+ return DoCopy(this, diagram, TRUE, dc, offsetX, offsetY);
+}
+
+// Universal copy function (to or from clipboard).
+// TODO:
+// Note that this only works for non-composites so far (nested shapes
+// don't have their old-to-new object mappings stored).
+// Also, lines don't yet get their attachment points moved to the new offset position
+// if they have more than 2 points.
+bool wxDiagramClipboard::DoCopy(wxDiagram* diagramFrom, wxDiagram* diagramTo, bool newIds,
+ wxDC* dc, int offsetX, int offsetY)
+{
+ OnStartCopy(diagramTo);
+
+ wxHashTable mapping(wxKEY_INTEGER);
+
+ // First copy all node shapes.
+ wxList* shapeList = diagramFrom->GetShapeList();
+ wxNode* node = shapeList->First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (((diagramFrom == this) || shape->Selected()) && !shape->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ wxShape* newShape = shape->CreateNewCopy();
+ newShape->GetLines().Clear();
+ if (newIds)
+ {
+ newShape->AssignNewIds();
+ }
+ mapping.Put((long) shape, (wxObject*) newShape);
+
+ newShape->SetX(newShape->GetX() + offsetX);
+ newShape->SetY(newShape->GetY() + offsetY);
+
+ OnAddShape(diagramTo, newShape, dc);
+
+ }
+ node = node->Next();
+ }
+
+ node = shapeList->First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (((diagramFrom == this) || shape->Selected()) && shape->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ wxLineShape* lineShape = (wxLineShape*) shape;
+ // Only copy a line if its ends are selected too.
+ if ((diagramFrom == this) || (lineShape->GetTo()->Selected() && lineShape->GetFrom()->Selected()))
+ {
+ wxLineShape* newShape = (wxLineShape*) shape->CreateNewCopy();
+ mapping.Put((long) shape, (wxObject*) newShape);
+
+ if (newIds)
+ newShape->AssignNewIds();
+
+ wxShape* fromShape = (wxShape*) mapping.Get((long) lineShape->GetFrom());
+ wxShape* toShape = (wxShape*) mapping.Get((long) lineShape->GetTo());
+
+ wxASSERT_MSG( (fromShape != NULL), "Could not find 'from' shape");
+ wxASSERT_MSG( (toShape != NULL), "Could not find 'to' shape");
+
+ fromShape->AddLine(newShape, toShape, newShape->GetAttachmentFrom(),
+ newShape->GetAttachmentTo());
+
+ OnAddShape(diagramTo, newShape, dc);
+
+ }
+ }
+ node = node->Next();
+ }
+
+ // Now make sure line ordering is correct
+ node = shapeList->First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (((diagramFrom == this) || shape->Selected()) && !shape->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ wxShape* newShape = (wxShape*) mapping.Get((long) shape);
+
+ // Make a list of all the new lines, in the same order as the old lines.
+ // Then apply the list of new lines to the shape.
+ wxList newLines;
+ wxNode* lineNode = shape->GetLines().First();
+ while (lineNode)
+ {
+ wxLineShape* lineShape = (wxLineShape*) lineNode->Data();
+ if ((diagramFrom == this) || (lineShape->GetTo()->Selected() && lineShape->GetFrom()->Selected()))
+ {
+ wxLineShape* newLineShape = (wxLineShape*) mapping.Get((long) lineShape);
+
+ wxASSERT_MSG( (newLineShape != NULL), "Could not find new line shape");
+
+ newLines.Append(newLineShape);
+ }
+
+ lineNode = lineNode->Next();
+ }
+
+ if (newLines.Number() > 0)
+ newShape->ApplyAttachmentOrdering(newLines);
+ }
+ node = node->Next();
+ }
+
+ OnEndCopy(diagramTo);
+
+ return TRUE;
+}
+
+#ifdef __WXMSW__
+// Draw contents to a Windows metafile device context and a bitmap, and copy
+// these to the Windows clipboard
+bool wxDiagramClipboard::CopyToClipboard(double scale)
+{
+ // Make a metafile DC
+ wxMetaFileDC mfDC;
+ if (mfDC.Ok())
+ {
+ mfDC.SetUserScale(scale, scale);
+
+ // Draw on metafile DC
+ Redraw(mfDC);
+
+ int printWidth = mfDC.MaxX() - mfDC.MinX();
+ int printHeight = mfDC.MaxY() - mfDC.MinY();
+ int maxX = (int)mfDC.MaxX();
+ int maxY = (int)mfDC.MaxY();
+ wxMetaFile *mf = mfDC.Close();
+
+ // Set to a bitmap memory DC
+ wxBitmap *newBitmap = new wxBitmap((int)(maxX + 10), (int)(maxY + 10));
+ if (!newBitmap->Ok())
+ {
+ delete newBitmap;
+
+ char buf[200];
+ sprintf(buf, "Sorry, could not allocate clipboard bitmap (%dx%d)", (maxX+10), (maxY+10));
+ wxMessageBox(buf, "Clipboard copy problem");
+ return FALSE;
+ }
+
+ wxMemoryDC memDC;
+ memDC.SelectObject(*newBitmap);
+ memDC.Clear();
+
+ // Now draw on memory bitmap DC
+ Redraw(memDC);
+
+ memDC.SelectObject(wxNullBitmap);
+
+ // Open clipboard and set the data
+ if (wxOpenClipboard())
+ {
+ wxEmptyClipboard();
+
+ // Copy the bitmap to the clipboard
+ wxSetClipboardData(wxDF_BITMAP, newBitmap, 0, 0);
+
+ if (mf)
+ {
+ // Copy the metafile to the clipboard
+ // Allow a small margin
+ bool success = mf->SetClipboard((int)(mfDC.MaxX() + 15), (int)(mfDC.MaxY() + 15));
+ }
+
+ // Close clipboard
+ wxCloseClipboard();
+ }
+
+ delete newBitmap;
+ delete mf;
+
+ }
+ return TRUE;
+}
+#endif
+ // __WXMSW__
+
+// Override this to e.g. have the shape added through a Do/Undo command system.
+// By default, we'll just add it directly to the destination diagram.
+bool wxDiagramClipboard::OnAddShape(wxDiagram* diagramTo, wxShape* newShape, wxDC* dc)
+{
+ diagramTo->AddShape(newShape);
+
+ if (dc && (diagramTo != this))
+ {
+ newShape->Select(TRUE, dc);
+ }
+
+ return TRUE;
+}
+
+/*
+ * csDiagramClipboard
+ */
+
+IMPLEMENT_DYNAMIC_CLASS(csDiagramClipboard, wxDiagramClipboard)
+
+// Start/end copying
+bool csDiagramClipboard::OnStartCopy(wxDiagram* diagramTo)
+{
+ // Do nothing if copying to the clipboard
+ if (diagramTo == this)
+ return TRUE;
+
+ // Deselect all objects initially.
+
+ csDiagram* diagram = (csDiagram*) diagramTo;
+ csDiagramDocument* doc = diagram->GetDocument();
+ ((csDiagramView*)doc->GetFirstView())->SelectAll(FALSE);
+
+ m_currentCmd = new csDiagramCommand("Paste", doc);
+
+ return TRUE;
+}
+
+bool csDiagramClipboard::OnEndCopy(wxDiagram* diagramTo)
+{
+ // Do nothing if copying to the clipboard
+ if (diagramTo == this)
+ return TRUE;
+
+ csDiagram* diagram = (csDiagram*) diagramTo;
+ csDiagramDocument* doc = diagram->GetDocument();
+
+ if (m_currentCmd)
+ {
+ if (m_currentCmd->GetStates().Number() == 0)
+ {
+ delete m_currentCmd;
+ }
+ else
+ {
+ doc->GetCommandProcessor()->Submit(m_currentCmd);
+ m_currentCmd = NULL;
+ }
+ }
+ return TRUE;
+}
+
+// Use the command framework to add the shapes, if we're copying to a diagram and
+// not the clipboard.
+bool csDiagramClipboard::OnAddShape(wxDiagram* diagramTo, wxShape* newShape, wxDC* dc)
+{
+ if (diagramTo == this)
+ {
+ diagramTo->AddShape(newShape);
+ }
+ else
+ {
+ csDiagram* diagram = (csDiagram*) diagramTo;
+ csDiagramDocument* doc = diagram->GetDocument();
+
+ if (newShape->IsKindOf(CLASSINFO(wxLineShape)))
+ m_currentCmd->AddState(new csCommandState(ID_CS_ADD_LINE_SELECT, newShape, NULL));
+ else
+ m_currentCmd->AddState(new csCommandState(ID_CS_ADD_SHAPE_SELECT, newShape, NULL));
+ }
+
+ return TRUE;
+}
+
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: dialogs.cpp
+// Purpose: Implements Studio dialogs
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+// #pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include <wx/wxprec.h>
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+#include <wx/resource.h>
+#include "dialogs.h"
+#include "doc.h"
+#include "view.h"
+#include "studio.h"
+#include "studio_resources.h"
+
+IMPLEMENT_CLASS(csLabelEditingDialog, wxDialog)
+
+BEGIN_EVENT_TABLE(csLabelEditingDialog, wxDialog)
+ EVT_BUTTON(wxID_OK, csLabelEditingDialog::OnOK)
+END_EVENT_TABLE()
+
+csLabelEditingDialog::csLabelEditingDialog(wxWindow* parent)
+{
+ LoadFromResource(parent, "shape_label_dialog");
+
+ // Accelerators
+ wxAcceleratorEntry entries[1];
+ entries[0].Set(wxACCEL_CTRL, WXK_RETURN, wxID_OK);
+ wxAcceleratorTable accel(1, entries);
+ SetAcceleratorTable(accel);
+
+ Centre();
+
+ wxTextCtrl* textCtrl = (wxTextCtrl*) FindWindow(ID_LABELTEXT);
+ wxASSERT( (textCtrl != NULL) );
+
+// textCtrl->SetAcceleratorTable(accel);
+
+ textCtrl->SetFocus();
+}
+
+void csLabelEditingDialog::OnOK(wxCommandEvent& event)
+{
+ wxTextCtrl* textCtrl = (wxTextCtrl*) FindWindow(ID_LABELTEXT);
+ wxASSERT( (textCtrl != NULL) );
+
+ SetShapeLabel(textCtrl->GetValue());
+
+ wxDialog::OnOK(event);
+}
+
+void csLabelEditingDialog::SetShapeLabel(const wxString& label)
+{
+ wxTextCtrl* textCtrl = (wxTextCtrl*) FindWindow(ID_LABELTEXT);
+ wxASSERT( (textCtrl != NULL) );
+
+ m_label = label;
+
+ textCtrl->SetValue(label);
+}
+
+IMPLEMENT_CLASS(csSettingsDialog, wxDialog)
+
+BEGIN_EVENT_TABLE(csSettingsDialog, wxDialog)
+ EVT_BUTTON(wxID_OK, csSettingsDialog::OnOK)
+END_EVENT_TABLE()
+
+#define PROPERTY_DIALOG_WIDTH 400
+#define PROPERTY_DIALOG_HEIGHT 400
+
+// For 400x400 settings dialog, size your panels to about 375x325 in dialog editor
+
+csSettingsDialog::csSettingsDialog(wxWindow* parent):
+ wxDialog(parent, -1, "Settings", wxPoint(0, 0), wxSize(PROPERTY_DIALOG_WIDTH, PROPERTY_DIALOG_HEIGHT))
+{
+ m_generalSettings = NULL;
+ m_diagramSettings = NULL;
+
+ m_notebook = new wxNotebook(this, ID_PROPERTY_NOTEBOOK,
+ wxPoint(2, 2), wxSize(PROPERTY_DIALOG_WIDTH - 4, PROPERTY_DIALOG_HEIGHT - 4));
+
+ m_generalSettings = new wxPanel;
+
+ bool success = m_generalSettings->LoadFromResource(m_notebook, "general_settings_dialog");
+ wxASSERT_MSG( (success), "Could not load general settings panel.");
+ m_notebook->AddPage(m_generalSettings, "General", TRUE);
+
+ m_diagramSettings = new wxPanel;
+
+ success = m_diagramSettings->LoadFromResource(m_notebook, "diagram_settings_dialog");
+ wxASSERT_MSG( (success), "Could not load diagram settings panel.");
+ m_notebook->AddPage(m_diagramSettings, "Diagram");
+
+ int largeButtonWidth = 70;
+ int largeButtonHeight = 22;
+
+ wxButton* okButton = new wxButton(this, wxID_OK, "OK", wxPoint(0, 0), wxSize(largeButtonWidth, largeButtonHeight));
+ wxButton* cancelButton = new wxButton(this, wxID_CANCEL, "Cancel", wxPoint(0, 0), wxSize(largeButtonWidth, largeButtonHeight));
+ wxButton* helpButton = new wxButton(this, wxID_HELP, "Help", wxPoint(0, 0), wxSize(largeButtonWidth, largeButtonHeight));
+
+ // Constraints for the notebook
+ wxLayoutConstraints *c = new wxLayoutConstraints;
+ c->top.SameAs (this, wxTop, 5);
+ c->left.SameAs (this, wxLeft, 5);
+ c->right.SameAs (this, wxRight, 5);
+ c->bottom.SameAs (cancelButton, wxTop, 5);
+ m_notebook->SetConstraints(c);
+
+ // Constraints for the Help button
+ c = new wxLayoutConstraints;
+ c->width.AsIs();
+ c->height.AsIs();
+ c->right.SameAs (this, wxRight, 5);
+ c->bottom.SameAs (this, wxBottom, 5);
+ helpButton->SetConstraints(c);
+
+ // Constraints for the Cancel button
+ c = new wxLayoutConstraints;
+ c->width.AsIs();
+ c->height.AsIs();
+ c->right.SameAs (helpButton, wxLeft, 5);
+ c->bottom.SameAs (this, wxBottom, 5);
+ cancelButton->SetConstraints(c);
+
+ // Constraints for the OK button
+ c = new wxLayoutConstraints;
+ c->width.AsIs();
+ c->height.AsIs();
+ c->right.SameAs (cancelButton, wxLeft, 5);
+ c->bottom.SameAs (this, wxBottom, 5);
+ okButton->SetConstraints(c);
+
+ okButton->SetDefault();
+ okButton->SetFocus();
+
+ Layout();
+ Centre(wxBOTH);
+}
+
+void csSettingsDialog::OnOK(wxCommandEvent& event)
+{
+ wxDialog::OnOK(event);
+}
+
+bool csSettingsDialog::TransferDataToWindow()
+{
+ wxTextCtrl* gridSpacing = (wxTextCtrl*) m_diagramSettings->FindWindow(ID_GRID_SPACING);
+ wxASSERT_MSG( (gridSpacing != (wxTextCtrl*) NULL), "Could not find grid spacing control.");
+
+ wxChoice* gridStyle = (wxChoice*) m_diagramSettings->FindWindow(ID_GRID_STYLE);
+ wxASSERT_MSG( (gridStyle != (wxChoice*) NULL), "Could not find grid style control.");
+
+ gridStyle->SetSelection(wxGetApp().GetGridStyle());
+
+ wxString str;
+ str.Printf("%d", wxGetApp().GetGridSpacing());
+ gridSpacing->SetValue(str);
+
+ return TRUE;
+}
+
+bool csSettingsDialog::TransferDataFromWindow()
+{
+ wxTextCtrl* gridSpacing = (wxTextCtrl*) m_diagramSettings->FindWindow(ID_GRID_SPACING);
+ wxASSERT_MSG( (gridSpacing != (wxTextCtrl*) NULL), "Could not find grid spacing control.");
+
+ wxChoice* gridStyle = (wxChoice*) m_diagramSettings->FindWindow(ID_GRID_STYLE);
+ wxASSERT_MSG( (gridStyle != (wxChoice*) NULL), "Could not find grid style control.");
+
+ wxGetApp().SetGridStyle(gridStyle->GetSelection());
+ wxGetApp().SetGridSpacing(atoi(gridSpacing->GetValue()));
+
+ if (wxGetApp().GetGridStyle() == csGRID_STYLE_DOTTED)
+ {
+ wxMessageBox("Dotted grid style not yet implemented.", "Studio", wxICON_EXCLAMATION);
+ return FALSE;
+ }
+
+ // Apply settings to all open diagram documents
+ wxNode* node = wxGetApp().GetDocManager()->GetDocuments().First();
+ while (node)
+ {
+ wxDocument* doc = (wxDocument*) node->Data();
+ if (doc->IsKindOf(CLASSINFO(csDiagramDocument)))
+ {
+ csDiagramDocument* diagramDoc = (csDiagramDocument*) doc;
+ wxDiagram* diagram = (wxDiagram*) diagramDoc->GetDiagram();
+
+ diagram->SetGridSpacing((double) wxGetApp().GetGridSpacing());
+ switch (wxGetApp().GetGridStyle())
+ {
+ case csGRID_STYLE_NONE:
+ {
+ diagram->SetSnapToGrid(FALSE);
+ break;
+ }
+ case csGRID_STYLE_INVISIBLE:
+ {
+ diagram->SetSnapToGrid(TRUE);
+ break;
+ }
+ case csGRID_STYLE_DOTTED:
+ {
+ // TODO (not implemented in OGL)
+ break;
+ }
+ }
+ }
+ node = node->Next();
+ }
+
+ return TRUE;
+}
+
+/*
+ * Shape properties dialog (tabbed)
+ */
+
+
+IMPLEMENT_CLASS(csShapePropertiesDialog, wxDialog)
+
+BEGIN_EVENT_TABLE(csShapePropertiesDialog, wxDialog)
+ EVT_BUTTON(wxID_OK, csShapePropertiesDialog::OnOK)
+END_EVENT_TABLE()
+
+#define SHAPE_PROPERTY_DIALOG_WIDTH 400
+#define SHAPE_PROPERTY_DIALOG_HEIGHT 400
+
+// For 400x400 settings dialog, size your panels to about 375x325 in dialog editor
+
+csShapePropertiesDialog::csShapePropertiesDialog(wxWindow* parent, const wxString& title,
+ wxPanel* attributeDialog, const wxString& attributeDialogName):
+ wxDialog(parent, -1, title, wxPoint(0, 0), wxSize(SHAPE_PROPERTY_DIALOG_WIDTH, SHAPE_PROPERTY_DIALOG_HEIGHT))
+{
+ m_attributeDialog = attributeDialog;
+ m_alternativeAttributeDialog = NULL;
+ m_generalPropertiesDialog = NULL;
+
+ m_notebook = new wxNotebook(this, ID_SHAPE_PROPERTY_NOTEBOOK,
+ wxPoint(2, 2), wxSize(SHAPE_PROPERTY_DIALOG_WIDTH - 4, SHAPE_PROPERTY_DIALOG_HEIGHT - 4));
+
+ m_generalPropertiesDialog = new csGeneralShapePropertiesDialog;
+ bool success = m_generalPropertiesDialog->LoadFromResource(m_notebook, "general_shape_properties_dialog");
+ wxASSERT_MSG( (success), "Could not load general properties panel.");
+ m_notebook->AddPage(m_generalPropertiesDialog, "General");
+
+ success = m_attributeDialog->LoadFromResource(m_notebook, attributeDialogName);
+ if (!success)
+ {
+ wxMessageBox("Could not load the attribute dialog for this shape.", "Studio", wxICON_EXCLAMATION);
+ delete m_attributeDialog;
+ m_attributeDialog = NULL;
+ }
+ else
+ {
+ m_notebook->AddPage(m_attributeDialog, "Attributes");
+ }
+
+ // Try the alternative dialog (test code)
+ wxString str(attributeDialogName);
+ str += "1";
+ m_alternativeAttributeDialog = new wxPanel;
+ success = m_alternativeAttributeDialog->LoadFromResource(m_notebook, str);
+ if (success)
+ {
+ m_notebook->AddPage(m_alternativeAttributeDialog, "Attributes (alternative)");
+ }
+ else
+ {
+ delete m_alternativeAttributeDialog;
+ m_alternativeAttributeDialog = NULL;
+ }
+
+ int largeButtonWidth = 70;
+ int largeButtonHeight = 22;
+
+ wxButton* okButton = new wxButton(this, wxID_OK, "OK", wxPoint(0, 0), wxSize(largeButtonWidth, largeButtonHeight));
+ wxButton* cancelButton = new wxButton(this, wxID_CANCEL, "Cancel", wxPoint(0, 0), wxSize(largeButtonWidth, largeButtonHeight));
+ wxButton* helpButton = new wxButton(this, wxID_HELP, "Help", wxPoint(0, 0), wxSize(largeButtonWidth, largeButtonHeight));
+
+ // Constraints for the notebook
+ wxLayoutConstraints *c = new wxLayoutConstraints;
+ c->top.SameAs (this, wxTop, 5);
+ c->left.SameAs (this, wxLeft, 5);
+ c->right.SameAs (this, wxRight, 5);
+ c->bottom.SameAs (helpButton, wxTop, 5);
+ m_notebook->SetConstraints(c);
+
+ // Constraints for the Help button
+ c = new wxLayoutConstraints;
+ c->width.AsIs();
+ c->height.AsIs();
+ c->right.SameAs (this, wxRight, 5);
+ c->bottom.SameAs (this, wxBottom, 5);
+ helpButton->SetConstraints(c);
+
+ // Constraints for the Cancel button
+ c = new wxLayoutConstraints;
+ c->width.AsIs();
+ c->height.AsIs();
+ c->right.SameAs (helpButton, wxLeft, 5);
+ c->bottom.SameAs (this, wxBottom, 5);
+ cancelButton->SetConstraints(c);
+
+ // Constraints for the OK button
+ c = new wxLayoutConstraints;
+ c->width.AsIs();
+ c->height.AsIs();
+ c->right.SameAs (cancelButton, wxLeft, 5);
+ c->bottom.SameAs (this, wxBottom, 5);
+ okButton->SetConstraints(c);
+
+ okButton->SetDefault();
+ okButton->SetFocus();
+
+ SetDefaults();
+
+ Layout();
+ Centre(wxBOTH);
+}
+
+void csShapePropertiesDialog::OnOK(wxCommandEvent& event)
+{
+ wxTextCtrl* textCtrl = (wxTextCtrl*) m_generalPropertiesDialog->FindWindow(ID_LABELTEXT);
+ wxASSERT( (textCtrl != NULL) );
+
+ m_generalPropertiesDialog->SetShapeLabel(textCtrl->GetValue());
+
+ wxDialog::OnOK(event);
+}
+
+// Set some suitable defaults in the attribute dialogs (in the first instance,
+// just set all wxChoices to the first element)
+void csShapePropertiesDialog::SetDefaults()
+{
+ if (!m_attributeDialog)
+ return;
+
+ wxNode* node = m_attributeDialog->GetChildren().First();
+ while (node)
+ {
+ wxWindow* child = (wxWindow*) node->Data();
+ if (child->IsKindOf(CLASSINFO(wxChoice)))
+ {
+ wxChoice* choice = (wxChoice*) child;
+ choice->SetSelection(0);
+ }
+ node = node->Next();
+ }
+
+ if (!m_alternativeAttributeDialog)
+ return;
+
+ node = m_alternativeAttributeDialog->GetChildren().First();
+ while (node)
+ {
+ wxWindow* child = (wxWindow*) node->Data();
+ if (child->IsKindOf(CLASSINFO(wxChoice)))
+ {
+ wxChoice* choice = (wxChoice*) child;
+ choice->SetSelection(0);
+ }
+ node = node->Next();
+ }
+}
+
+/*
+ * csGeneralShapePropertiesDialog
+ */
+
+IMPLEMENT_CLASS(csGeneralShapePropertiesDialog, wxPanel)
+
+BEGIN_EVENT_TABLE(csGeneralShapePropertiesDialog, wxPanel)
+END_EVENT_TABLE()
+
+csGeneralShapePropertiesDialog::csGeneralShapePropertiesDialog()
+{
+}
+
+void csGeneralShapePropertiesDialog::SetShapeLabel(const wxString& label)
+{
+ wxTextCtrl* textCtrl = (wxTextCtrl*) FindWindow(ID_LABELTEXT);
+ wxASSERT( (textCtrl != NULL) );
+
+ m_label = label;
+
+ textCtrl->SetValue(label);
+}
+
+/*
+ * csThinRectangleDialog
+ */
+
+IMPLEMENT_CLASS(csThinRectangleDialog, wxPanel)
+
+BEGIN_EVENT_TABLE(csThinRectangleDialog, wxPanel)
+END_EVENT_TABLE()
+
+csThinRectangleDialog::csThinRectangleDialog()
+{
+}
+
+/*
+ * csWideRectangleDialog
+ */
+
+IMPLEMENT_CLASS(csWideRectangleDialog, wxPanel)
+
+BEGIN_EVENT_TABLE(csWideRectangleDialog, wxPanel)
+END_EVENT_TABLE()
+
+csWideRectangleDialog::csWideRectangleDialog()
+{
+}
+
+/*
+ * csTriangleDialog
+ */
+
+IMPLEMENT_CLASS(csTriangleDialog, wxPanel)
+
+BEGIN_EVENT_TABLE(csTriangleDialog, wxPanel)
+END_EVENT_TABLE()
+
+csTriangleDialog::csTriangleDialog()
+{
+}
+
+/*
+ * csSemiCircleDialog
+ */
+
+IMPLEMENT_CLASS(csSemiCircleDialog, wxPanel)
+
+BEGIN_EVENT_TABLE(csSemiCircleDialog, wxPanel)
+END_EVENT_TABLE()
+
+csSemiCircleDialog::csSemiCircleDialog()
+{
+}
+
+/*
+ * csCircleDialog
+ */
+
+IMPLEMENT_CLASS(csCircleDialog, wxPanel)
+
+BEGIN_EVENT_TABLE(csCircleDialog, wxPanel)
+END_EVENT_TABLE()
+
+csCircleDialog::csCircleDialog()
+{
+}
+
+/*
+ * csCircleShadowDialog
+ */
+
+IMPLEMENT_CLASS(csCircleShadowDialog, wxPanel)
+
+BEGIN_EVENT_TABLE(csCircleShadowDialog, wxPanel)
+END_EVENT_TABLE()
+
+csCircleShadowDialog::csCircleShadowDialog()
+{
+}
+
+/*
+ * csOctagonDialog
+ */
+
+IMPLEMENT_CLASS(csOctagonDialog, wxPanel)
+
+BEGIN_EVENT_TABLE(csOctagonDialog, wxPanel)
+END_EVENT_TABLE()
+
+csOctagonDialog::csOctagonDialog()
+{
+}
+
+/*
+ * csGroupDialog
+ */
+
+IMPLEMENT_CLASS(csGroupDialog, wxPanel)
+
+BEGIN_EVENT_TABLE(csGroupDialog, wxPanel)
+END_EVENT_TABLE()
+
+csGroupDialog::csGroupDialog()
+{
+}
+
+/*
+ * csTextBoxDialog
+ */
+
+IMPLEMENT_CLASS(csTextBoxDialog, wxPanel)
+
+BEGIN_EVENT_TABLE(csTextBoxDialog, wxPanel)
+END_EVENT_TABLE()
+
+csTextBoxDialog::csTextBoxDialog()
+{
+}
+
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: dialogs.h
+// Purpose: Miscellaneous dialogs
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _STUDIO_DIALOGS_H_
+#define _STUDIO_DIALOGS_H_
+
+#ifdef __GNUG__
+// #pragma interface
+#endif
+
+#include <wx/wx.h>
+#include <wx/notebook.h>
+
+/*
+ * Label editing dialog (about to become obsolete)
+ */
+
+class csLabelEditingDialog: public wxDialog
+{
+DECLARE_CLASS(csLabelEditingDialog)
+public:
+ csLabelEditingDialog(wxWindow* parent);
+
+ void SetShapeLabel(const wxString& label);
+ inline wxString GetShapeLabel() const { return m_label; }
+
+ void OnOK(wxCommandEvent& event);
+
+protected:
+ wxString m_label;
+
+DECLARE_EVENT_TABLE()
+};
+
+/*
+ * Settings dialog (tabbed)
+ */
+
+class csSettingsDialog: public wxDialog
+{
+DECLARE_CLASS(csSettingsDialog)
+public:
+ csSettingsDialog(wxWindow* parent);
+
+ void OnOK(wxCommandEvent& event);
+
+ virtual bool TransferDataToWindow();
+ virtual bool TransferDataFromWindow();
+
+protected:
+
+ wxPanel* m_generalSettings;
+ wxPanel* m_diagramSettings;
+ wxNotebook* m_notebook;
+
+DECLARE_EVENT_TABLE()
+};
+
+#define ID_PROPERTY_NOTEBOOK 1000
+#define ID_GENERAL_SETTINGS 1002
+#define ID_DIAGRAM_SETTINGS 1003
+
+/*
+ * csGeneralShapePropertiesDialog
+ * Name, description etc.
+ */
+
+class csGeneralShapePropertiesDialog: public wxPanel
+{
+DECLARE_CLASS(csGeneralShapePropertiesDialog)
+public:
+ csGeneralShapePropertiesDialog();
+
+ void SetShapeLabel(const wxString& label);
+ inline wxString GetShapeLabel() const { return m_label; }
+
+protected:
+ wxString m_label;
+
+DECLARE_EVENT_TABLE()
+};
+
+/*
+ * Shape properties dialog (tabbed)
+ */
+
+class csShapePropertiesDialog: public wxDialog
+{
+DECLARE_CLASS(csShapePropertiesDialog)
+public:
+ csShapePropertiesDialog(wxWindow* parent, const wxString& title, wxPanel* attributeDialog, const wxString& attributeDialogName);
+
+ void OnOK(wxCommandEvent& event);
+
+ // Set some suitable defaults in the attribute dialogs (in the first instance,
+ // just set all wxChoices to the first element)
+ void SetDefaults();
+
+// Accessors
+ csGeneralShapePropertiesDialog* GetGeneralPropertiesDialog() const { return m_generalPropertiesDialog; }
+
+
+protected:
+
+ // Attributes, specific to each shape
+ wxPanel* m_attributeDialog;
+ wxPanel* m_alternativeAttributeDialog;
+
+ // General properties, same for each shape, e.g. name/description
+ csGeneralShapePropertiesDialog* m_generalPropertiesDialog;
+
+ wxNotebook* m_notebook;
+
+DECLARE_EVENT_TABLE()
+};
+
+#define ID_SHAPE_PROPERTY_NOTEBOOK 1000
+
+//// Specific attribute-editing panel classes below here
+
+/*
+ * csThinRectangleDialog
+ */
+
+class csThinRectangleDialog: public wxPanel
+{
+DECLARE_CLASS(csThinRectangleDialog)
+public:
+ csThinRectangleDialog();
+
+DECLARE_EVENT_TABLE()
+};
+
+/*
+ * csWideRectangleDialog
+ */
+
+class csWideRectangleDialog: public wxPanel
+{
+DECLARE_CLASS(csWideRectangleDialog)
+public:
+ csWideRectangleDialog();
+
+DECLARE_EVENT_TABLE()
+};
+
+/*
+ * csTriangleDialog
+ */
+
+class csTriangleDialog: public wxPanel
+{
+DECLARE_CLASS(csTriangleDialog)
+public:
+ csTriangleDialog();
+
+DECLARE_EVENT_TABLE()
+};
+
+/*
+ * csSemiCircleDialog
+ */
+
+class csSemiCircleDialog: public wxPanel
+{
+DECLARE_CLASS(csSemiCircleDialog)
+public:
+ csSemiCircleDialog();
+
+DECLARE_EVENT_TABLE()
+};
+
+/*
+ * csCircleDialog
+ */
+
+class csCircleDialog: public wxPanel
+{
+DECLARE_CLASS(csCircleDialog)
+public:
+ csCircleDialog();
+
+DECLARE_EVENT_TABLE()
+};
+
+/*
+ * csCircleShadowDialog
+ */
+
+class csCircleShadowDialog: public wxPanel
+{
+DECLARE_CLASS(csCircleShadowDialog)
+public:
+ csCircleShadowDialog();
+
+DECLARE_EVENT_TABLE()
+};
+
+/*
+ * csOctagonDialog
+ */
+
+class csOctagonDialog: public wxPanel
+{
+DECLARE_CLASS(csOctagonDialog)
+public:
+ csOctagonDialog();
+
+DECLARE_EVENT_TABLE()
+};
+
+/*
+ * csGroupDialog
+ */
+
+class csGroupDialog: public wxPanel
+{
+DECLARE_CLASS(csGroupDialog)
+public:
+ csGroupDialog();
+
+DECLARE_EVENT_TABLE()
+};
+
+/*
+ * csTextBoxDialog
+ */
+
+class csTextBoxDialog: public wxPanel
+{
+DECLARE_CLASS(csTextBoxDialog)
+public:
+ csTextBoxDialog();
+
+DECLARE_EVENT_TABLE()
+};
+
+
+#endif
+ // _STUDIO_DIALOGS_H_
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: doc.cpp
+// Purpose: Implements document functionality
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+// #pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include <wx/wxprec.h>
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+#include <wx/wxexpr.h>
+
+#include "studio.h"
+#include "doc.h"
+#include "view.h"
+#include "basicp.h"
+
+IMPLEMENT_DYNAMIC_CLASS(csDiagramDocument, wxDocument)
+
+#ifdef _MSC_VER
+#pragma warning(disable:4355)
+#endif
+
+csDiagramDocument::csDiagramDocument():m_diagram(this)
+{
+}
+
+#ifdef _MSC_VER
+#pragma warning(default:4355)
+#endif
+
+csDiagramDocument::~csDiagramDocument()
+{
+}
+
+bool csDiagramDocument::OnCloseDocument()
+{
+ m_diagram.DeleteAllShapes();
+ return TRUE;
+}
+
+bool csDiagramDocument::OnSaveDocument(const wxString& file)
+{
+ if (file == "")
+ return FALSE;
+
+ if (!m_diagram.SaveFile(file))
+ {
+ wxString msgTitle;
+ if (wxTheApp->GetAppName() != "")
+ msgTitle = wxTheApp->GetAppName();
+ else
+ msgTitle = wxString("File error");
+
+ (void)wxMessageBox("Sorry, could not open this file for saving.", msgTitle, wxOK | wxICON_EXCLAMATION,
+ GetDocumentWindow());
+ return FALSE;
+ }
+
+ Modify(FALSE);
+ SetFilename(file);
+ return TRUE;
+}
+
+bool csDiagramDocument::OnOpenDocument(const wxString& file)
+{
+ if (!OnSaveModified())
+ return FALSE;
+
+ wxString msgTitle;
+ if (wxTheApp->GetAppName() != "")
+ msgTitle = wxTheApp->GetAppName();
+ else
+ msgTitle = wxString("File error");
+
+ m_diagram.DeleteAllShapes();
+ if (!m_diagram.LoadFile(file))
+ {
+ (void)wxMessageBox("Sorry, could not open this file.", msgTitle, wxOK|wxICON_EXCLAMATION,
+ GetDocumentWindow());
+ return FALSE;
+ }
+ SetFilename(file, TRUE);
+ Modify(FALSE);
+ UpdateAllViews();
+
+ return TRUE;
+}
+
+
+/*
+ * Implementation of drawing command
+ */
+
+csDiagramCommand::csDiagramCommand(const wxString& name, csDiagramDocument *doc,
+ csCommandState* onlyState):
+ wxCommand(TRUE, name)
+{
+ m_doc = doc;
+
+ if (onlyState)
+ {
+ AddState(onlyState);
+ }
+}
+
+csDiagramCommand::~csDiagramCommand()
+{
+ wxNode* node = m_states.First();
+ while (node)
+ {
+ csCommandState* state = (csCommandState*) node->Data();
+ delete state;
+ node = node->Next();
+ }
+}
+
+void csDiagramCommand::AddState(csCommandState* state)
+{
+ state->m_doc = m_doc;
+// state->m_cmd = m_cmd;
+ m_states.Append(state);
+}
+
+// Insert a state at the beginning of the list
+void csDiagramCommand::InsertState(csCommandState* state)
+{
+ state->m_doc = m_doc;
+// state->m_cmd = m_cmd;
+ m_states.Insert(state);
+}
+
+// Schedule all lines connected to the states to be cut.
+void csDiagramCommand::RemoveLines()
+{
+ wxNode* node = m_states.First();
+ while (node)
+ {
+ csCommandState* state = (csCommandState*) node->Data();
+ wxShape* shape = state->GetShapeOnCanvas();
+ wxASSERT( (shape != NULL) );
+
+ wxNode *node1 = shape->GetLines().First();
+ while (node1)
+ {
+ wxLineShape *line = (wxLineShape *)node1->Data();
+ if (!FindStateByShape(line))
+ {
+ csCommandState* newState = new csCommandState(ID_CS_CUT, NULL, line);
+ InsertState(newState);
+ }
+
+ node1 = node1->Next();
+ }
+ node = node->Next();
+ }
+}
+
+csCommandState* csDiagramCommand::FindStateByShape(wxShape* shape)
+{
+ wxNode* node = m_states.First();
+ while (node)
+ {
+ csCommandState* state = (csCommandState*) node->Data();
+ if (shape == state->GetShapeOnCanvas() || shape == state->GetSavedState())
+ return state;
+ node = node->Next();
+ }
+ return NULL;
+}
+
+bool csDiagramCommand::Do()
+{
+ wxNode* node = m_states.First();
+ while (node)
+ {
+ csCommandState* state = (csCommandState*) node->Data();
+ if (!state->Do())
+ return FALSE;
+ node = node->Next();
+ }
+ return TRUE;
+}
+
+bool csDiagramCommand::Undo()
+{
+ // Undo in reverse order, so e.g. shapes get added
+ // back before the lines do.
+ wxNode* node = m_states.Last();
+ while (node)
+ {
+ csCommandState* state = (csCommandState*) node->Data();
+ if (!state->Undo())
+ return FALSE;
+ node = node->Previous();
+ }
+ return TRUE;
+}
+
+csCommandState::csCommandState(int cmd, wxShape* savedState, wxShape* shapeOnCanvas)
+{
+ m_cmd = cmd;
+ m_doc = NULL;
+ m_savedState = savedState;
+ m_shapeOnCanvas = shapeOnCanvas;
+ m_linePositionFrom = 0;
+ m_linePositionTo = 0;
+}
+
+csCommandState::~csCommandState()
+{
+ if (m_savedState)
+ {
+ m_savedState->SetCanvas(NULL);
+ delete m_savedState;
+ }
+}
+
+bool csCommandState::Do()
+{
+ switch (m_cmd)
+ {
+ case ID_CS_CUT:
+ {
+ // New state is 'nothing' - maybe pass shape ID to state so we know what
+ // we're talking about.
+ // Then save old shape in m_savedState (actually swap pointers)
+
+ wxASSERT( (m_shapeOnCanvas != NULL) );
+ wxASSERT( (m_savedState == NULL) ); // new state will be 'nothing'
+ wxASSERT( (m_doc != NULL) );
+
+ wxShapeCanvas* canvas = m_shapeOnCanvas->GetCanvas();
+
+ // In case this is a line
+ wxShape* lineFrom = NULL;
+ wxShape* lineTo = NULL;
+ int attachmentFrom = 0, attachmentTo = 0;
+
+ if (m_shapeOnCanvas->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ // Store the from/to info to save in the line shape
+ wxLineShape* lineShape = (wxLineShape*) m_shapeOnCanvas;
+ lineFrom = lineShape->GetFrom();
+ lineTo = lineShape->GetTo();
+ attachmentFrom = lineShape->GetAttachmentFrom();
+ attachmentTo = lineShape->GetAttachmentTo();
+
+ m_linePositionFrom = lineFrom->GetLinePosition(lineShape);
+ m_linePositionTo = lineTo->GetLinePosition(lineShape);
+ }
+
+ m_shapeOnCanvas->Select(FALSE);
+ ((csDiagramView*) m_doc->GetFirstView())->SelectShape(m_shapeOnCanvas, FALSE);
+
+ m_shapeOnCanvas->Unlink();
+
+ m_doc->GetDiagram()->RemoveShape(m_shapeOnCanvas);
+
+ m_savedState = m_shapeOnCanvas;
+
+ if (m_savedState->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ // Restore the from/to info for future reference
+ wxLineShape* lineShape = (wxLineShape*) m_savedState;
+ lineShape->SetFrom(lineFrom);
+ lineShape->SetTo(lineTo);
+ lineShape->SetAttachments(attachmentFrom, attachmentTo);
+
+ wxClientDC dc(canvas);
+ canvas->PrepareDC(dc);
+
+ lineFrom->MoveLinks(dc);
+ lineTo->MoveLinks(dc);
+ }
+
+ m_doc->Modify(TRUE);
+ m_doc->UpdateAllViews();
+ break;
+ }
+ case ID_CS_ADD_SHAPE:
+ case ID_CS_ADD_SHAPE_SELECT:
+ {
+ // The app has given the command state a new m_savedState
+ // shape, which is the new shape to add to the canvas (but
+ // not actually added until this point).
+ // The new 'saved state' is therefore 'nothing' since there
+ // was nothing there before.
+
+ wxASSERT( (m_shapeOnCanvas == NULL) );
+ wxASSERT( (m_savedState != NULL) );
+ wxASSERT( (m_doc != NULL) );
+
+ m_shapeOnCanvas = m_savedState;
+ m_savedState = NULL;
+
+ m_doc->GetDiagram()->AddShape(m_shapeOnCanvas);
+ m_shapeOnCanvas->Show(TRUE);
+
+ wxClientDC dc(m_shapeOnCanvas->GetCanvas());
+ m_shapeOnCanvas->GetCanvas()->PrepareDC(dc);
+
+ csEvtHandler *handler = (csEvtHandler *)m_shapeOnCanvas->GetEventHandler();
+ m_shapeOnCanvas->FormatText(dc, handler->m_label);
+
+ m_shapeOnCanvas->Move(dc, m_shapeOnCanvas->GetX(), m_shapeOnCanvas->GetY());
+
+ if (m_cmd == ID_CS_ADD_SHAPE_SELECT)
+ {
+ m_shapeOnCanvas->Select(TRUE, &dc);
+ ((csDiagramView*) m_doc->GetFirstView())->SelectShape(m_shapeOnCanvas, TRUE);
+ }
+
+ m_doc->Modify(TRUE);
+ m_doc->UpdateAllViews();
+ break;
+ }
+ case ID_CS_ADD_LINE:
+ case ID_CS_ADD_LINE_SELECT:
+ {
+ wxASSERT( (m_shapeOnCanvas == NULL) );
+ wxASSERT( (m_savedState != NULL) );
+ wxASSERT( (m_doc != NULL) );
+
+ wxLineShape *lineShape = (wxLineShape *)m_savedState;
+ wxASSERT( (lineShape->GetFrom() != NULL) );
+ wxASSERT( (lineShape->GetTo() != NULL) );
+
+ m_shapeOnCanvas = m_savedState;
+ m_savedState = NULL;
+
+ m_doc->GetDiagram()->AddShape(lineShape);
+
+ lineShape->GetFrom()->AddLine(lineShape, lineShape->GetTo(),
+ lineShape->GetAttachmentFrom(), lineShape->GetAttachmentTo());
+
+ lineShape->Show(TRUE);
+
+ wxClientDC dc(lineShape->GetCanvas());
+ lineShape->GetCanvas()->PrepareDC(dc);
+
+ // It won't get drawn properly unless you move both
+ // connected images
+ lineShape->GetFrom()->Move(dc, lineShape->GetFrom()->GetX(), lineShape->GetFrom()->GetY());
+ lineShape->GetTo()->Move(dc, lineShape->GetTo()->GetX(), lineShape->GetTo()->GetY());
+
+ if (m_cmd == ID_CS_ADD_LINE_SELECT)
+ {
+ lineShape->Select(TRUE, &dc);
+ ((csDiagramView*) m_doc->GetFirstView())->SelectShape(m_shapeOnCanvas, TRUE);
+ }
+
+ m_doc->Modify(TRUE);
+ m_doc->UpdateAllViews();
+ break;
+ }
+ case ID_CS_CHANGE_BACKGROUND_COLOUR:
+ case ID_CS_MOVE:
+ case ID_CS_SIZE:
+ case ID_CS_EDIT_PROPERTIES:
+ case ID_CS_FONT_CHANGE:
+ case ID_CS_ARROW_CHANGE:
+ case ID_CS_ROTATE_CLOCKWISE:
+ case ID_CS_ROTATE_ANTICLOCKWISE:
+ case ID_CS_CHANGE_LINE_ORDERING:
+ case ID_CS_CHANGE_LINE_ATTACHMENT:
+ case ID_CS_ALIGN:
+ case ID_CS_NEW_POINT:
+ case ID_CS_CUT_POINT:
+ case ID_CS_MOVE_LINE_POINT:
+ case ID_CS_STRAIGHTEN:
+ case ID_CS_MOVE_LABEL:
+ {
+ // At this point we have been given a new shape
+ // just like the old one but with a changed colour.
+ // It's now time to apply that change to the
+ // shape on the canvas, saving the old state.
+ // NOTE: this is general enough to work with MOST attribute
+ // changes!
+
+ wxASSERT( (m_shapeOnCanvas != NULL) );
+ wxASSERT( (m_savedState != NULL) ); // This is the new shape with changed colour
+ wxASSERT( (m_doc != NULL) );
+
+ wxClientDC dc(m_shapeOnCanvas->GetCanvas());
+ m_shapeOnCanvas->GetCanvas()->PrepareDC(dc);
+
+ bool isSelected = m_shapeOnCanvas->Selected();
+ if (isSelected)
+ m_shapeOnCanvas->Select(FALSE, & dc);
+
+ if (m_cmd == ID_CS_SIZE || m_cmd == ID_CS_ROTATE_CLOCKWISE || m_cmd == ID_CS_ROTATE_ANTICLOCKWISE ||
+ m_cmd == ID_CS_CHANGE_LINE_ORDERING || m_cmd == ID_CS_CHANGE_LINE_ATTACHMENT)
+ {
+ m_shapeOnCanvas->Erase(dc);
+ }
+
+ // TODO: make sure the ID is the same. Or, when applying the new state,
+ // don't change the original ID.
+ wxShape* tempShape = m_shapeOnCanvas->CreateNewCopy();
+
+ // Apply the saved state to the shape on the canvas, by copying.
+ m_savedState->CopyWithHandler(*m_shapeOnCanvas);
+
+ // Delete this state now it's been used (m_shapeOnCanvas currently holds this state)
+ delete m_savedState;
+
+ // Remember the previous state
+ m_savedState = tempShape;
+
+ // Redraw the shape
+
+ if (m_cmd == ID_CS_MOVE || m_cmd == ID_CS_ROTATE_CLOCKWISE || m_cmd == ID_CS_ROTATE_ANTICLOCKWISE ||
+ m_cmd == ID_CS_ALIGN)
+ {
+ m_shapeOnCanvas->Move(dc, m_shapeOnCanvas->GetX(), m_shapeOnCanvas->GetY());
+
+ csEvtHandler *handler = (csEvtHandler *)m_shapeOnCanvas->GetEventHandler();
+ m_shapeOnCanvas->FormatText(dc, handler->m_label);
+ m_shapeOnCanvas->Draw(dc);
+ }
+ else if (m_cmd == ID_CS_CHANGE_LINE_ORDERING)
+ {
+ m_shapeOnCanvas->MoveLinks(dc);
+ }
+ else if (m_cmd == ID_CS_CHANGE_LINE_ATTACHMENT)
+ {
+ wxLineShape *lineShape = (wxLineShape *)m_shapeOnCanvas;
+
+ // Have to move both sets of links since we don't know which links
+ // have been affected (unless we compared before and after states).
+ lineShape->GetFrom()->MoveLinks(dc);
+ lineShape->GetTo()->MoveLinks(dc);
+ }
+ else if (m_cmd == ID_CS_SIZE)
+ {
+ double width, height;
+ m_shapeOnCanvas->GetBoundingBoxMax(&width, &height);
+
+ m_shapeOnCanvas->SetSize(width, height);
+ m_shapeOnCanvas->Move(dc, m_shapeOnCanvas->GetX(), m_shapeOnCanvas->GetY());
+
+ m_shapeOnCanvas->Show(TRUE);
+
+ // Recursively redraw links if we have a composite.
+ if (m_shapeOnCanvas->GetChildren().Number() > 0)
+ m_shapeOnCanvas->DrawLinks(dc, -1, TRUE);
+
+ m_shapeOnCanvas->GetEventHandler()->OnEndSize(width, height);
+ }
+ else if (m_cmd == ID_CS_EDIT_PROPERTIES || m_cmd == ID_CS_FONT_CHANGE)
+ {
+ csEvtHandler *handler = (csEvtHandler *)m_shapeOnCanvas->GetEventHandler();
+ m_shapeOnCanvas->FormatText(dc, handler->m_label);
+ m_shapeOnCanvas->Draw(dc);
+ }
+ else
+ {
+ m_shapeOnCanvas->Draw(dc);
+ }
+
+ if (isSelected)
+ m_shapeOnCanvas->Select(TRUE, & dc);
+
+ m_doc->Modify(TRUE);
+ m_doc->UpdateAllViews();
+
+ break;
+ }
+ }
+ return TRUE;
+}
+
+bool csCommandState::Undo()
+{
+ switch (m_cmd)
+ {
+ case ID_CS_CUT:
+ {
+ wxASSERT( (m_savedState != NULL) );
+ wxASSERT( (m_doc != NULL) );
+
+ m_doc->GetDiagram()->AddShape(m_savedState);
+ m_shapeOnCanvas = m_savedState;
+ m_savedState = NULL;
+
+ if (m_shapeOnCanvas->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ wxLineShape* lineShape = (wxLineShape*) m_shapeOnCanvas;
+ lineShape->GetFrom()->AddLine(lineShape, lineShape->GetTo(),
+ lineShape->GetAttachmentFrom(), lineShape->GetAttachmentTo(),
+ m_linePositionFrom, m_linePositionTo);
+
+ wxShapeCanvas* canvas = lineShape->GetFrom()->GetCanvas();
+
+ wxClientDC dc(canvas);
+ canvas->PrepareDC(dc);
+
+ lineShape->GetFrom()->MoveLinks(dc);
+ lineShape->GetTo()->MoveLinks(dc);
+
+ }
+ m_shapeOnCanvas->Show(TRUE);
+
+ m_doc->Modify(TRUE);
+ m_doc->UpdateAllViews();
+ break;
+ }
+ case ID_CS_ADD_SHAPE:
+ case ID_CS_ADD_LINE:
+ case ID_CS_ADD_SHAPE_SELECT:
+ case ID_CS_ADD_LINE_SELECT:
+ {
+ wxASSERT( (m_shapeOnCanvas != NULL) );
+ wxASSERT( (m_savedState == NULL) );
+ wxASSERT( (m_doc != NULL) );
+
+ // In case this is a line
+ wxShape* lineFrom = NULL;
+ wxShape* lineTo = NULL;
+ int attachmentFrom = 0, attachmentTo = 0;
+
+ if (m_shapeOnCanvas->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ // Store the from/to info to save in the line shape
+ wxLineShape* lineShape = (wxLineShape*) m_shapeOnCanvas;
+ lineFrom = lineShape->GetFrom();
+ lineTo = lineShape->GetTo();
+ attachmentFrom = lineShape->GetAttachmentFrom();
+ attachmentTo = lineShape->GetAttachmentTo();
+ }
+
+ wxClientDC dc(m_shapeOnCanvas->GetCanvas());
+ m_shapeOnCanvas->GetCanvas()->PrepareDC(dc);
+
+ m_shapeOnCanvas->Select(FALSE, &dc);
+ ((csDiagramView*) m_doc->GetFirstView())->SelectShape(m_shapeOnCanvas, FALSE);
+ m_doc->GetDiagram()->RemoveShape(m_shapeOnCanvas);
+ m_shapeOnCanvas->Unlink(); // Unlinks the line, if it is a line
+
+ if (m_shapeOnCanvas->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ // Restore the from/to info for future reference
+ wxLineShape* lineShape = (wxLineShape*) m_shapeOnCanvas;
+ lineShape->SetFrom(lineFrom);
+ lineShape->SetTo(lineTo);
+ lineShape->SetAttachments(attachmentFrom, attachmentTo);
+ }
+
+ m_savedState = m_shapeOnCanvas;
+ m_shapeOnCanvas = NULL;
+
+ m_doc->Modify(TRUE);
+ m_doc->UpdateAllViews();
+ break;
+ }
+ case ID_CS_CHANGE_BACKGROUND_COLOUR:
+ case ID_CS_MOVE:
+ case ID_CS_SIZE:
+ case ID_CS_EDIT_PROPERTIES:
+ case ID_CS_FONT_CHANGE:
+ case ID_CS_ARROW_CHANGE:
+ case ID_CS_ROTATE_CLOCKWISE:
+ case ID_CS_ROTATE_ANTICLOCKWISE:
+ case ID_CS_CHANGE_LINE_ORDERING:
+ case ID_CS_CHANGE_LINE_ATTACHMENT:
+ case ID_CS_ALIGN:
+ case ID_CS_NEW_POINT:
+ case ID_CS_CUT_POINT:
+ case ID_CS_MOVE_LINE_POINT:
+ case ID_CS_STRAIGHTEN:
+ case ID_CS_MOVE_LABEL:
+ {
+ // Exactly like the Do case; we're just swapping states.
+ Do();
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: doc.h
+// Purpose: Document classes
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _STUDIO_DOC_H_
+#define _STUDIO_DOC_H_
+
+#ifdef __GNUG__
+// #pragma interface
+#endif
+
+#include <wx/docview.h>
+#include <wx/string.h>
+#include <wx/wxexpr.h>
+
+#include "ogl.h"
+#include "shapes.h"
+
+/*
+ * A diagram document, which contains a diagram.
+ */
+
+class csDiagramDocument: public wxDocument
+{
+ DECLARE_DYNAMIC_CLASS(csDiagramDocument)
+public:
+ csDiagramDocument();
+ ~csDiagramDocument();
+
+ bool OnSaveDocument(const wxString& file);
+ bool OnOpenDocument(const wxString& file);
+
+ inline wxDiagram *GetDiagram() { return &m_diagram; }
+
+ bool OnCloseDocument();
+
+protected:
+ csDiagram m_diagram;
+};
+
+/*
+ Do/Undo 30/7/98
+
+ 1) We have a csCommandState, and in csDiagramCommand you have a list of
+ these. This allows undo to work with several shapes at once.
+
+ 2) Instead of storing info about each operation, e.g. separate pens, colours,
+ etc., we simply use a copy of the shape.
+ In csCommandState, we have a pointer to the actual shape in the canvas, m_currentShape.
+ We also have wxShape* m_shapeState which stores the requested or previous state
+ (depending on whether it's before the Do or after the Do.
+
+ - In Do: save a temp copy of the old m_currentShape (i.e. the state just before it's changed).
+ Change the data pointed to by m_currentShape to the new attributes stored in m_shapeState.
+ Now assign the temp copy to m_shapeState, for use in Undo.
+
+ wxShape* temp = m_currentShape->Copy(); // Take a copy of the current state
+ m_currentShape->Set(m_shapeState); // Apply the new state (e.g. moving, changing colour etc.)
+ delete m_shapeState; // Delete the previous 'old state'.
+ m_shapeState = temp; // Remember the new 'old state'.
+
+ */
+
+
+class csCommandState;
+class csDiagramCommand: public wxCommand
+{
+ friend class csCommandState;
+ public:
+ // Multi-purpose constructor for creating, deleting shapes
+ csDiagramCommand(const wxString& name, csDiagramDocument *doc,
+ csCommandState* onlyState = NULL); // Allow for the common case of just one state to change
+
+ ~csDiagramCommand();
+
+ bool Do();
+ bool Undo();
+
+ // Add a state to the end of the list
+ void AddState(csCommandState* state);
+
+ // Insert a state at the beginning of the list
+ void InsertState(csCommandState* state);
+
+ // Schedule all lines connected to the states to be cut.
+ void RemoveLines();
+
+ // Find the state that refers to this shape
+ csCommandState* FindStateByShape(wxShape* shape);
+
+ wxList& GetStates() const { return (wxList&) m_states; }
+
+ protected:
+ csDiagramDocument* m_doc;
+ wxList m_states;
+};
+
+class csCommandState: public wxObject
+{
+ friend class csDiagramCommand;
+public:
+ csCommandState(int cmd, wxShape* savedState, wxShape* shapeOnCanvas);
+ ~csCommandState();
+
+ bool Do();
+ bool Undo();
+
+ inline void SetSavedState(wxShape *s) { m_savedState = s; }
+ inline wxShape *GetSavedState() const { return m_savedState; }
+
+ inline void SetShapeOnCanvas(wxShape *s) { m_shapeOnCanvas = s; }
+ inline wxShape *GetShapeOnCanvas() const { return m_shapeOnCanvas; }
+protected:
+ wxShape* m_savedState; // Previous state, for restoring on Undo
+ wxShape* m_shapeOnCanvas; // The actual shape on the canvas
+ csDiagramDocument* m_doc;
+ int m_cmd;
+
+ // These store the line ordering for the shapes at either end,
+ // so an un-cut line can restore the ordering properly. Otherwise
+ // it just adds the line at an arbitrary position.
+ int m_linePositionFrom;
+ int m_linePositionTo;
+};
+
+#endif
+ // _STUDIO_DOC_H_
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: mainfrm.cpp
+// Purpose: Studio main frame
+// Author: Julian Smart
+// Modified by:
+// Created: 27/7/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#include "wx/mdi.h"
+#endif
+
+#include "wx/laywin.h"
+
+#include "studio.h"
+#include "view.h"
+#include "doc.h"
+#include "cspalette.h"
+#include "mainfrm.h"
+#include "dialogs.h"
+
+BEGIN_EVENT_TABLE(csFrame, wxDocMDIParentFrame)
+ EVT_MENU(ID_CS_ABOUT, csFrame::OnAbout)
+ EVT_MENU(wxID_EXIT, csFrame::OnQuit)
+ EVT_MENU(wxID_HELP, csFrame::OnHelp)
+ EVT_MENU(ID_CS_SETTINGS, csFrame::OnSettings)
+ EVT_SIZE(csFrame::OnSize)
+ EVT_SASH_DRAGGED(ID_LAYOUT_WINDOW_PALETTE, csFrame::OnSashDragPaletteWindow)
+ EVT_SASH_DRAGGED(ID_LAYOUT_WINDOW_PROJECT, csFrame::OnSashDragProjectWindow)
+ EVT_IDLE(csFrame::OnIdle)
+ EVT_UPDATE_UI(wxID_PRINT, csFrame::OnUpdateDisable)
+ EVT_UPDATE_UI(wxID_PREVIEW, csFrame::OnUpdateDisable)
+ EVT_UPDATE_UI(wxID_SAVE, csFrame::OnSaveUpdate)
+ EVT_UPDATE_UI(wxID_SAVEAS, csFrame::OnSaveUpdate)
+ EVT_UPDATE_UI(wxID_UNDO, csFrame::OnUpdateDisable)
+ EVT_UPDATE_UI(wxID_REDO, csFrame::OnUpdateDisable)
+ EVT_UPDATE_UI(wxID_CUT, csFrame::OnUpdateDisable)
+ EVT_UPDATE_UI(wxID_COPY, csFrame::OnUpdateDisable)
+ EVT_UPDATE_UI(wxID_PASTE, csFrame::OnUpdateDisable)
+ EVT_CLOSE(csFrame::OnCloseWindow)
+END_EVENT_TABLE()
+
+// Define my frame constructor
+csFrame::csFrame(wxDocManager* manager, wxFrame *parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size,
+ long style):
+ wxDocMDIParentFrame(manager, parent, id, title, pos, size, style, "frame")
+{
+ CreateToolBar(wxNO_BORDER|wxTB_FLAT|wxTB_HORIZONTAL);
+ wxGetApp().InitToolBar(GetToolBar());
+
+ // Accelerators
+ wxAcceleratorEntry entries[4];
+
+ entries[0].Set(wxACCEL_NORMAL, WXK_F1, wxID_HELP);
+ entries[1].Set(wxACCEL_CTRL, 'O', wxID_OPEN);
+ entries[2].Set(wxACCEL_CTRL, 'N', wxID_NEW);
+ entries[3].Set(wxACCEL_CTRL, 'P', wxID_PRINT);
+
+ wxAcceleratorTable accel(4, entries);
+ SetAcceleratorTable(accel);
+}
+
+void csFrame::OnHelp(wxCommandEvent& event)
+{
+ wxGetApp().GetHelpController().DisplayContents();
+}
+
+void csFrame::OnSettings(wxCommandEvent& event)
+{
+ csSettingsDialog* dialog = new csSettingsDialog(this);
+ int ret = dialog->ShowModal();
+ dialog->Destroy();
+}
+
+void csFrame::OnQuit(wxCommandEvent& event)
+{
+ Close(TRUE);
+}
+
+void csFrame::OnAbout(wxCommandEvent& event)
+{
+ (void)wxMessageBox("OGL Studio\n(c) 1999, Julian Smart", "About OGL Studio", wxICON_INFORMATION);
+}
+
+void csFrame::OnSashDragPaletteWindow(wxSashEvent& event)
+{
+ if (event.GetDragStatus() == wxSASH_STATUS_OUT_OF_RANGE)
+ return;
+
+ switch (event.GetId())
+ {
+ case ID_LAYOUT_WINDOW_PALETTE:
+ {
+ wxGetApp().GetDiagramPaletteSashWindow()->SetDefaultSize(wxSize(10000, event.GetDragRect().height));
+ break;
+ }
+ }
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame(this);
+}
+
+void csFrame::OnSashDragProjectWindow(wxSashEvent& event)
+{
+ if (event.GetDragStatus() == wxSASH_STATUS_OUT_OF_RANGE)
+ return;
+
+ switch (event.GetId())
+ {
+ case ID_LAYOUT_WINDOW_PROJECT:
+ {
+ wxGetApp().GetProjectSashWindow()->SetDefaultSize(wxSize(event.GetDragRect().width, 10000));
+ break;
+ }
+ }
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame(this);
+}
+
+// Define the behaviour for the frame closing
+// - must delete all frames except for the main one.
+void csFrame::OnCloseWindow(wxCloseEvent& event)
+{
+ int x, y;
+ GetPosition(& x, & y);
+ wxGetApp().m_mainFramePos = wxPoint(x, y);
+
+ GetSize(& x, & y);
+ wxGetApp().m_mainFrameSize = wxSize(x, y);
+
+ wxDocMDIParentFrame::OnCloseWindow(event);
+}
+
+void csFrame::OnSize(wxSizeEvent& event)
+{
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame(this);
+}
+
+// Make sure the correct toolbars are showing for the active view
+void csFrame::OnIdle(wxIdleEvent& event)
+{
+ wxFrame::OnIdle(event);
+
+ wxSashLayoutWindow* paletteWin = wxGetApp().GetDiagramPaletteSashWindow();
+ wxSashLayoutWindow* diagramToolBarWin = wxGetApp().GetDiagramToolBarSashWindow();
+ if (!paletteWin || !diagramToolBarWin)
+ return;
+ bool doLayout = FALSE;
+ if (GetActiveChild())
+ {
+ if (!paletteWin->IsShown() || !diagramToolBarWin->IsShown())
+ {
+ paletteWin->Show(TRUE);
+ diagramToolBarWin->Show(TRUE);
+
+ doLayout = TRUE;
+ }
+ }
+ else
+ {
+ if (paletteWin->IsShown() || diagramToolBarWin->IsShown())
+ {
+ paletteWin->Show(FALSE);
+ diagramToolBarWin->Show(FALSE);
+ doLayout = TRUE;
+ }
+ }
+ if (doLayout)
+ {
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame(this);
+ }
+}
+
+// General handler for disabling items
+void csFrame::OnUpdateDisable(wxUpdateUIEvent& event)
+{
+ event.Enable(FALSE);
+}
+
+void csFrame::OnSaveUpdate(wxUpdateUIEvent& event)
+{
+ event.Enable( (GetActiveChild() != NULL) );
+}
+
+/*
+ * Child frame
+ */
+
+BEGIN_EVENT_TABLE(csMDIChildFrame, wxDocMDIChildFrame)
+ EVT_ACTIVATE(csMDIChildFrame::OnActivate)
+END_EVENT_TABLE()
+
+csMDIChildFrame::csMDIChildFrame(wxDocument* doc, wxView* view, wxMDIParentFrame *parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style):
+ wxDocMDIChildFrame(doc, view, parent, id, title, pos, size, style)
+{
+ // Accelerators
+ wxAcceleratorEntry entries[18];
+
+ // Usual editing functions
+ entries[0].Set(wxACCEL_NORMAL, WXK_DELETE, wxID_CLEAR);
+ entries[1].Set(wxACCEL_CTRL, 'X', wxID_CUT);
+ entries[2].Set(wxACCEL_CTRL, 'C', wxID_COPY);
+ entries[3].Set(wxACCEL_SHIFT, WXK_INSERT, wxID_PASTE);
+ entries[4].Set(wxACCEL_CTRL, 'V', wxID_PASTE);
+ entries[5].Set(wxACCEL_CTRL, 'A', ID_CS_SELECT_ALL);
+
+ // Undo/redo
+ entries[6].Set(wxACCEL_CTRL, 'Z', wxID_UNDO);
+ entries[7].Set(wxACCEL_CTRL, 'Y', wxID_REDO);
+
+ // Other
+ entries[8].Set(wxACCEL_NORMAL, WXK_RETURN, ID_CS_EDIT_PROPERTIES);
+ entries[9].Set(wxACCEL_ALT, WXK_RETURN, ID_CS_EDIT_PROPERTIES);
+ entries[10].Set(wxACCEL_CTRL, 'D', wxID_DUPLICATE);
+ entries[11].Set(wxACCEL_NORMAL, WXK_F1, wxID_HELP);
+
+ // File handling
+ entries[12].Set(wxACCEL_CTRL, 'S', wxID_SAVE);
+ entries[13].Set(wxACCEL_NORMAL, WXK_F12, wxID_SAVEAS);
+ entries[14].Set(wxACCEL_CTRL, 'O', wxID_OPEN);
+ entries[15].Set(wxACCEL_CTRL, 'N', wxID_NEW);
+ entries[16].Set(wxACCEL_CTRL, 'P', wxID_PRINT);
+ entries[17].Set(wxACCEL_CTRL, 'W', wxID_CLOSE);
+
+
+ wxAcceleratorTable accel(18, entries);
+ SetAcceleratorTable(accel);
+}
+
+void csMDIChildFrame::OnActivate(wxActivateEvent& event)
+{
+ wxDocMDIChildFrame::OnActivate(event);
+/*
+ wxSashLayoutWindow* win = wxGetApp().GetDiagramPaletteSashWindow();
+ if (!win)
+ return;
+
+ win->Show(event.GetActive());
+
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame((wxMDIParentFrame*) GetParent());
+*/
+}
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: mainfrm.h
+// Purpose: Studio main window class
+// Author: Julian Smart
+// Modified by:
+// Created: 27/7/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _STUDIO_MAINFRM_H_
+#define _STUDIO_MAINFRM_H_
+
+#include <wx/docmdi.h>
+
+class wxSashLayoutWindow;
+class wxSashEvent;
+
+class csFrame: public wxDocMDIParentFrame
+{
+ public:
+ csFrame(wxDocManager *manager, wxFrame *parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style);
+
+ void OnCloseWindow(wxCloseEvent& event);
+ void OnSize(wxSizeEvent& event);
+ void OnAbout(wxCommandEvent& event);
+ void OnNewWindow(wxCommandEvent& event);
+ void OnQuit(wxCommandEvent& event);
+ void OnSashDragPaletteWindow(wxSashEvent& event);
+ void OnSashDragProjectWindow(wxSashEvent& event);
+ void OnIdle(wxIdleEvent& event);
+ void OnHelp(wxCommandEvent& event);
+ void OnSettings(wxCommandEvent& event);
+
+ // General handler for disabling items
+ void OnUpdateDisable(wxUpdateUIEvent& event);
+ void OnSaveUpdate(wxUpdateUIEvent& event);
+
+DECLARE_EVENT_TABLE()
+};
+
+class csMDIChildFrame: public wxDocMDIChildFrame
+{
+ public:
+ csMDIChildFrame(wxDocument* doc, wxView* view, wxMDIParentFrame *parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style);
+
+ void OnActivate(wxActivateEvent& event);
+
+DECLARE_EVENT_TABLE()
+};
+
+#endif
+ // _STUDIO_MAINFRM_H_
+
--- /dev/null
+#
+# File: makefile.unx
+# Author: Julian Smart
+# Created: 1998
+# Updated:
+# Copyright: (c) 1998 Julian Smart
+#
+# "%W% %G%"
+#
+# Makefile for OGL Studio (UNIX).
+
+PROGRAM=studio
+
+OBJECTS=$(PROGRAM).o doc.o shapes.o symbols.o view.o cspalette.o\
+ mainfrm.o project.o dialogs.o csprint.o
+
+EXTRACPPFLAGS=-I$(WXDIR)/utils/ogl/src
+EXTRALDLIBS=-logl$(GUISUFFIX)
+
+WXDIR=/home/jacs/wx2
+
+include $(WXDIR)/src/makeprog.env
+
+cleanogl:
+ cd $(WXDIR)/utils/ogl/src; make -f makefile.unx cleanmotif
+
+ogl:
+ cd $(WXDIR)/utils/ogl/src; make -f makefile.unx motif
+
+wx:
+ cd $(WXDIR)/src/motif; make -f makefile.unx motif
+
+cleanwx:
+ cd $(WXDIR)/src/motif; make -f makefile.unx cleanmotif
+
+cleanall: cleanmotif cleanogl cleanwx
+
+makeall: wx ogl motif
+
--- /dev/null
+#
+# File: makefile.vc
+# Author: Julian Smart
+# Created: 1999
+# Updated:
+# Copyright: (c) Julian Smart
+#
+# "%W% %G%"
+#
+# Makefile : Builds OGL studio example (MS VC++).
+# Use FINAL=1 argument to nmake to build final version with no debugging
+# info
+
+# Set WXDIR for your system
+WXDIR = $(WXWIN)
+WXUSINGDLL=0
+
+STUDIODIR = $(WXDIR)\utils\ogl\samples\studio
+THISDIR = $(STUDIODIR)
+
+OGLDIR = $(WXDIR)\utils\ogl
+OGLINC = $(OGLDIR)\src
+OGLLIB = $(WXDIR)\lib\ogl.lib
+
+!include $(WXDIR)\src\makevc.env
+
+EXTRALIBS=$(OGLLIB)
+EXTRAINC = /I$(OGLINC)
+
+PROGRAM=studio
+
+OBJECTS = $(PROGRAM).obj doc.obj shapes.obj symbols.obj view.obj cspalette.obj\
+ mainfrm.obj project.obj dialogs.obj csprint.obj
+
+all: wx ogl $(PROGRAM).exe
+
+$(PROGRAM): $(PROGRAM).exe
+
+cleanall: clean cleanogl # cleanidelib
+cleanutils: cleanall
+
+wx:
+ cd $(WXDIR)\src\msw
+ nmake -f makefile.vc FINAL=$(FINAL)
+ cd $(THISDIR)
+
+cleanwx:
+ cd $(WXDIR)\src\msw
+ nmake -f makefile.vc clean
+ cd $(THISDIR)
+
+idelib:
+ cd $(CLIPDIR)\IDELib\src
+ nmake -f makefile.vc FINAL=$(FINAL)
+ cd $(THISDIR)
+
+cleanidelib:
+ cd $(CLIPDIR)\IDELib\src
+ nmake -f makefile.vc clean
+ cd $(THISDIR)
+
+ogl:
+ cd $(OGLDIR)\src
+ nmake -f makefile.vc FINAL=$(FINAL)
+ cd $(THISDIR)
+
+cleanogl:
+ cd $(OGLDIR)\src
+ nmake -f makefile.vc clean
+ cd $(THISDIR)
+
+$(PROGRAM).exe: $(DUMMYOBJ) $(WXLIB) $(OBJECTS) $(EXTRALIBS) $(PROGRAM).res
+ $(link) @<<
+-out:$(PROGRAM).exe
+$(LINKFLAGS)
+$(DUMMYOBJ) $(OBJECTS) $(PROGRAM).res
+$(LIBS)
+<<
+
+
+$(PROGRAM).obj: $(PROGRAM).$(SRCSUFF) cspalette.h doc.h view.h $(DUMMYOBJ)
+ $(cc) @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+mainfrm.obj: mainfrm.$(SRCSUFF) mainfrm.h
+ $(cc) @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+cspalette.obj: cspalette.$(SRCSUFF) cspalette.h
+ $(cc) @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+project.obj: project.$(SRCSUFF) project.h
+ $(cc) @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+view.obj: view.$(SRCSUFF) view.h
+ $(cc) @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+doc.obj: doc.$(SRCSUFF) doc.h
+ $(cc) @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+shapes.obj: shapes.$(SRCSUFF) shapes.h
+ $(cc) @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+symbols.obj: symbols.$(SRCSUFF) symbols.h
+ $(cc) @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+dialogs.obj: dialogs.$(SRCSUFF) dialogs.h
+ $(cc) @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+csprint.obj: csprint.$(SRCSUFF) shapes.h
+ $(cc) @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+$(OBJECTS): shapes.h doc.h view.h mainfrm.h studio.h cspalette.h project.h symbols.h dialogs.h
+
+$(PROGRAM).res : $(PROGRAM).rc $(WXDIR)\include\wx\msw\wx.rc
+ $(rc) -r /i$(WXDIR)\include -fo$@ $(PROGRAM).rc
+
+
+clean:
+ -erase *.obj
+ -erase *.exe
+ -erase *.res
+ -erase *.map
+ -erase *.sbr
+ -erase *.pdb
--- /dev/null
+#
+# File: Makefile
+# Author: Julian Smart
+# Created: 1998
+#
+# "%W% %G%"
+#
+# Makefile : Builds OGL Studio manual
+#
+
+DOCDIR=.
+LOCALDOCDIR=.
+
+DOCSOURCES=studio.tex
+
+hlp: studio.hlp
+html: studio.htm
+rtf: studio.rtf
+
+studio.hlp: studio.rtf studio.hpj
+ -erase studio.ph
+ hcw /E /C studio.hpj
+
+studio.rtf: $(DOCSOURCES)
+ -start /w tex2rtf studio.tex studio.rtf -twice -winhelp
+
+studio.htm: $(DOCSOURCES)
+ -start /w tex2rtf studio.tex studio.htm -twice -html
+
--- /dev/null
+; Tex2RTF initialisation file
+runTwice = yes
+titleFontSize = 12
+authorFontSize = 10
+chapterFontSize = 12
+sectionFontSize = 12
+subsectionFontSize = 12
+headerRule = yes
+footerRule = yes
+useHeadingStyles = yes
+contentsDepth = 2
+listItemIndent=40
+winHelpContents = yes
+winHelpVersion = 4 ; 3 for Windows 3.x, 4 for Windows 95
+winHelpTitle = "OGL Studio"
+generateHPJ = yes
+htmlBrowseButtons = bitmap
+truncateFilenames = yes
+htmlIndex = no
+htmlFrameContents = no
--- /dev/null
+\documentstyle[a4,makeidx,verbatim,texhelp,fancyhea,mysober,mytitle]{report}%
+\twocolwidtha{4cm}%
+\input{psbox.tex}
+\newcommand{\commandref}[2]{\helpref{{\tt $\backslash$#1}}{#2}}%
+\newcommand{\commandrefn}[2]{\helprefn{{\tt $\backslash$#1}}{#2}\index{#1}}%
+\newcommand{\commandpageref}[2]{\latexignore{\helprefn{{\tt $\backslash$#1}}{#2}}\latexonly{{\tt $\backslash$#1} {\it page \pageref{#2}}}\index{#1}}%
+\newcommand{\indexit}[1]{#1\index{#1}}%
+\newcommand{\inioption}[1]{{\tt #1}\index{#1}}%
+\parskip=10pt%
+\parindent=0pt%
+\title{Manual for OGL Studio}%
+\author{by Julian Smart}%
+\makeindex%
+\begin{document}%
+\maketitle%
+\pagestyle{fancyplain}%
+\bibliographystyle{plain}%
+\pagenumbering{arabic}%
+\setheader{{\it CONTENTS}}{}{}{}{}{{\it CONTENTS}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+\tableofcontents%
+
+\chapter{Welcome to OGL Studio}%
+\setheader{{\it Welcome}}{}{}{}{}{{\it Welcome}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+Welcome to OGL Studio, an extended sample for the Object Graphics Library.
+
+For release information, please see the \helpref{Read Me}{readme} section.
+
+\chapter{Read Me}\label{readme}%
+\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+\section{Change log}
+
+Version 1, February 7th, 1999
+
+\begin{itemize}\itemsep=0pt
+\item First release.
+\end{itemize}
+
+\section{Bugs}
+
+There are no known bugs.
+
+\begin{comment}
+\chapter{Getting Started}\label{gettingstarted}%
+\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+\end{comment}
+
+\chapter{Working with the diagram window}\label{schedule}%
+\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+This section describes how you work in the diagram window.
+
+In addition, you may wish to refer to the following sections:
+
+\begin{itemize}\itemsep=0pt
+\item \helpref{How To}{howto}
+%\item \helpref{Getting started}{gettingstarted}
+\item \helpref{Using Menu Commands}{menucommands}
+\item \helpref{Using Toolbar Commands}{toolbarcommands}
+\end{itemize}
+
+When you first run OGL Studio, there is a menubar, a single
+toolbar with commonly-used functionality such as loading and
+saving, a project window to the left, and an MDI (Multiple Document
+Interface) area to the right, which will contain documents.
+
+\section{Creating a diagram}
+
+To create a new diagram, click on "File|New" or the New tool.
+
+A blank document and two new toolbars will appear. The first
+new toolbar is the \helpref{diagramming formatting toolbar}{diagramformattingtoolbar}, and contains
+icons and controls for:
+
+\begin{itemize}\itemsep=0pt
+\item alignment and size cloning;
+\item arrow toggling;
+\item point size;
+\item zoom level.
+\end{itemize}
+
+The second new toolbar is called the \helpref{diagram palette}{diagrampalette} and contains:
+
+\begin{itemize}\itemsep=0pt
+\item a pointer tool used for selecting, moving and sizing objects;
+\item a text tool used for editing text or creating new text boxes;
+\item a tool for each of the symbols.
+\end{itemize}
+
+\section{Basic editing}
+
+To add a symbol, left-click on the symbol in the diagram palette,
+and then left-click on the document. The currently selected
+tool will revert to the pointer tool, so to add another object,
+click on the symbol again, then on the document.
+
+To draw a line between two objects, right-drag between the two
+objects, starting at the attachment point area you wish to start the
+line with, and ending at another appropriate attachment point
+area. The initial ordering of the lines may not be correct (lines
+may overlap, for example) so to reorder lines on a particular
+side of a object, select a line, then left-drag the desired end to a new
+position (tip: keep within the object perimeter). Left-dragging the
+line end can also be used to change the attachment point of that
+end of the line, to a new side or vertex (depending on the object).
+
+To select or deselect a object, left click the object. To select
+several objects at once, keep the shift key pressed down when
+left-clicking, or left-drag a 'lassoo' around several objects.
+
+To delete a object or line, select it and press the Delete key, or use
+"Edit|Clear", or right-click on the object to show a menu and choose
+the "Cut" item.
+
+If you are deleting a object which has one ore more lines
+attached, the lines are deleted prior to the object deletion.
+
+Shapes can be rotated by right-clicking and selecting "Rotate
+clockwise" or "Rotate anticlockwise".
+
+Line arrows can be added (pointing in the direction in which
+you created the line) by selecting the line and pressing the
+"Toggle arrow" tool on the formatting toolbar.
+
+\section{Adding text}
+
+Select the text tool (on the symbol palette) and left-click on
+a object. If you click outside a object on the document, you are
+prompted to add a new free-floating text box.
+
+Alternatively, you can select a object and press Return (or
+select the "Edit|Edit label" menu item); or right-click and
+select "Edit label" from the object menu.
+
+Change the point size using the combobox on the formatting
+toolbar.
+
+\section{Aligning objects}
+
+Select several objects and click on an alignment tool on
+the formatting toolbar. The alignment will be done with
+respect to the first object you select. You can also copy
+the size of a object to other objects with the "Copy size" tool.
+
+\section{Adding segments to lines and straightening them}
+
+To make a line have more than one segment, select the line,
+then press the "New line point" tool. Create as many new control points
+(and therefore segments) as you like. Then arrange the points
+into a rough approximation of how they should be laid out
+horizontally and vertically. Click on "Straighten lines" to
+tidy up the layout.
+
+To delete a line control point, select the line and click on
+"Cut line point" tool. An arbitrary point will be deleted.
+
+\section{Undo/Redo}
+
+Every operation can be undone, and then redone, back until
+the time at which you last saved your document. Use
+"Edit|Undo" and "Edit|Redo"; or the shortcuts Ctrl-Z and Ctrl-Y.
+
+\section{Loading and saving files}
+
+Load and save files using the main toolbar, or "File|Open...",
+"File|Save", "File|Save As..." menu items.
+
+\section{Copy and paste}
+
+OGL Studio has a diagram clipboard, into which you can copy selections. You can then
+paste the contents of clipboard into the same or another diagram window.
+
+Use "Edit|Copy" (or the toolbar copy button) to copy the selection. Use "Edit|Cut" (or the toolbar cut button) to
+copy and then delete the selection. Use "Edit|Paste" (or the toolbar paste button) to copy the selection to
+the current diagram window.
+
+Under Windows, copy and cutting also copies the selection to the Windows clipboard into metafile (vector)
+format, and Windows bitmap format. Note that not all Windows applications can accept the vector format.
+If the application seems to be pasting the wrong format into the document, try using that application's
+"Edit|Paste Special..." menu item, if one exists.
+
+\section{Keyboard shortcuts}
+
+The following keyboard shortcuts are available. {\bf Note:} The OGL Studio menus indicate which shortcuts are
+available.
+
+\begin{twocollist}\itemsep=0pt
+\twocolitem{Delete}{Clear selected object(s)}
+\twocolitem{Enter}{Edit text for selected object}
+\twocolitem{Ctrl-A}{Select all}
+\twocolitem{Ctrl-C}{Copy the selection to the clipboard}
+\twocolitem{Ctrl-D}{Duplicate the selection}
+\twocolitem{Ctrl-O}{Open a diagram}
+\twocolitem{Ctrl-N}{Create a new diagram}
+\twocolitem{Ctrl-P}{Print (not implemented)}
+\twocolitem{Ctrl-S}{Save the diagram file without prompting}
+\twocolitem{Ctrl-V}{Paste the selection}
+\twocolitem{Ctrl-W}{Close the current window}
+\twocolitem{Ctrl-X}{Cut the selection}
+\twocolitem{Ctrl-Z}{Undo last action}
+\twocolitem{Ctrl-Y}{Redo current action on the undo stack}
+\twocolitem{Ctrl-Enter}{Confirm the label editing operation (dismisses the dialog)}
+\twocolitem{Esc}{Cancel the label editing dialog}
+\twocolitem{F1}{Invoke the manual}
+\twocolitem{F12}{Save the diagram file, prompting for a filename}
+\end{twocollist}
+
+\chapter{Menu commands}\label{menucommands}%
+\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+This section describes the menu commands.
+
+\section{File}
+
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf New...}}{Creates a new diagram window.}
+\twocolitem{{\bf Open...}}{Opens a diagram file.}
+\twocolitem{{\bf Close}}{Closes the current window.}
+\twocolitem{{\bf Save}}{Saves the current diagram without prompting.}
+\twocolitem{{\bf Save As...}}{Saves the current diagram, prompting for a filename.}
+\twocolitem{{\bf Print...}}{Prints the current diagram (not implemented).}
+\twocolitem{{\bf Print Setup...}}{Invokes the printer setup dialog.}
+\twocolitem{{\bf Print Preview}}{Invokes print preview for this diagram (not implemented).}
+\twocolitem{{\bf Exit}}{Exits the program.}
+\end{twocollist}
+
+Further menu items appended to the end of the File menu allow you
+to load previously-saved diagram files quickly.
+
+\section{Edit}
+
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf Undo}}{Undoes the previous action.}
+\twocolitem{{\bf Redo}}{Redoes the previously undone action.}
+\twocolitem{{\bf Cut}}{Deletes the current selection and places it on the clipboard.}
+\twocolitem{{\bf Copy}}{Copies the current selection onto the clipboard, both to the internal
+diagram clipboard and under Windows, to the Windows clipboard, in metafile and bitmap formats.}
+\twocolitem{{\bf Paste}}{Pastes from the internal diagram clipboard to the currently active window.}
+\twocolitem{{\bf Duplicate}}{Duplicates the current selection, placing the objects further down and to the right.}
+\twocolitem{{\bf Clear}}{Clears the current selection without placing it on the clipboard.}
+\twocolitem{{\bf Select All}}{Selects all objects.}
+\twocolitem{{\bf Edit Label...}}{Invokes a dialog to edit the label of the currently selected object.}
+\end{twocollist}
+
+\begin{comment}%
+\section{View}
+
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf Toolbar}}{Toggles the toolbar on and off.}
+\twocolitem{{\bf Status Bar}}{Toggles the status bar on and off.}
+\twocolitem{{\bf Settings}}{Invokes the \helpref{Settings dialog}{settings} to allow you to adjust a variety of
+settings.}
+\end{twocollist}
+\end{comment}%
+
+\section{Window}
+
+The Window menu is shown when one or more child window is active.
+
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf Cascade}}{Arranges the child windows in a cascade.}
+\twocolitem{{\bf Tile}}{Arranges the child windows in a tiled formation.}
+\twocolitem{{\bf Arrange Icons}}{Arranges the minimized icons.}
+\twocolitem{{\bf Next}}{Activates the next MDI window.}
+\end{twocollist}
+
+Further menu items appended to the end of the Window menu allow you
+to restore and activate any child window.
+
+\section{Help}
+
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf Help Contents}}{Invokes the on-line help, showing the contents page.}
+\twocolitem{{\bf About}}{Displays a small dialog giving copyright and version information.}
+\end{twocollist}
+
+\chapter{Toolbar commands}\label{toolbarcommands}%
+\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+This section describes the commands associated with the various toolbars and diagram palette.
+
+\section{Main toolbar}\label{maintoolbar}
+
+The main toolbar is active all the time, with buttons greyed out if not appropriate to the current context.
+
+\begin{twocollist}
+\twocolitem{\image{1cm;0cm}{new.bmp}}{{\bf New} Creates a new diagram window.}
+\twocolitem{\image{1cm;0cm}{open.bmp}}{{\bf Open} Opens a diagram file.}
+\twocolitem{\image{1cm;0cm}{save.bmp}}{{\bf Save} Saves the current diagram without prompting.}
+\twocolitem{\image{1cm;0cm}{print.bmp}}{{\bf Print} Prints the current diagram (not implemented).}
+\twocolitem{\image{1cm;0cm}{copy.bmp}}{{\bf Copy} Copies the current selection onto the internal clipboard, and under Windows, into the Windows clipboard
+in metafile and bitmap formats.}
+\twocolitem{\image{1cm;0cm}{cut.bmp}}{{\bf Cut} Deletes the current selection and puts it on the clipboard.}
+\twocolitem{\image{1cm;0cm}{paste.bmp}}{{\bf Paste} Pastes the contents of the internal diagram clipboard onto the
+current diagram window.}
+\twocolitem{\image{1cm;0cm}{undo.bmp}}{{\bf Undo} Undoes the last command.}
+\twocolitem{\image{1cm;0cm}{redo.bmp}}{{\bf Redo} Redoes the last command.}
+\twocolitem{\image{1cm;0cm}{help.bmp}}{{\bf Help button} Invokes on-line help.}
+\end{twocollist}
+
+\section{Diagram formatting toolbar}\label{diagramformattingtoolbar}
+
+The diagram toolbar is visible only when a diagram window is active.
+
+\begin{twocollist}
+\twocolitem{\image{1cm;0cm}{alignl.bmp}}{{\bf Align left} Aligns the selected objects to the left side of the last selection.}
+\twocolitem{\image{1cm;0cm}{alignr.bmp}}{{\bf Align right} Aligns the selected objects to the right side of the last selection.}
+\twocolitem{\image{1cm;0cm}{alignt.bmp}}{{\bf Align top} Aligns the selected objects to the top side of the last selection.}
+\twocolitem{\image{1cm;0cm}{alignb.bmp}}{{\bf Align bottom} Aligns the selected objects to the bottom side of the last selection.}
+\twocolitem{\image{1cm;0cm}{horiz.bmp}}{{\bf Align horizontally} Aligns the selected objects to be centered horizontally with respect to the last selection.}
+\twocolitem{\image{1cm;0cm}{vert.bmp}}{{\bf Align vertically} Aligns the selected objects to be centered vertically with respect to the last selection.}
+\twocolitem{\image{1cm;0cm}{copysize.bmp}}{{\bf Copy size} Makes the selected objects the same size as the last selection.}
+\twocolitem{\image{1cm;0cm}{linearrow.bmp}}{{\bf Line arrow} Toggles an arrow on or off for the selected objects.}
+\twocolitem{\image{1cm;0cm}{newpoint.bmp}}{{\bf New point} Inserts a control point into the selected line(s).}
+\twocolitem{\image{1cm;0cm}{cutpoint.bmp}}{{\bf Cut point} Deletes a control point from the selected line(s).}
+\twocolitem{\image{1cm;0cm}{straight.bmp}}{{\bf Straighten} Straightens line segments that are nearly horizontal
+or vertical.}
+\twocolitem{\image{1cm;0cm}{pointsize.bmp}}{{\bf Point size} Allows selection of the point size for the current
+selection.}
+\twocolitem{\image{1cm;0cm}{zoom.bmp}}{{\bf Zoom control} Allows selection of the zoom level for the current diagram.}
+\end{twocollist}
+
+\section{Diagram palette}\label{diagrampalette}
+
+The diagram palette is visible only when a diagram window is active. It contains the tools for
+adding objects and text to a diagram.
+
+\begin{twocollist}
+\twocolitem{\image{1cm;0cm}{arrow.bmp}}{{\bf Pointer tool} Click on this to allow dragging and selection of objects.}
+\twocolitem{\image{1cm;0cm}{texttool.bmp}}{{\bf Text tool} Click on this, then click on objects or the diagram background
+to edit object or free-floating text labels.}
+\end{twocollist}
+
+The other tools on this palette represent demo objects.
+
+To place an object on a diagram, click on its symbol, then left-click on the diagram. You will need to click
+on the palette symbol each time you wish to create an object, since the palette selection reverts to the pointer tool
+after each object is created.
+
+\chapter{Dialogs}\label{dialogs}%
+\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+To be written.
+
+\chapter{How To}\label{howto}%
+\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+\section{Create a new object}
+
+Create a new diagram window if you have not already. Then:
+
+\begin{itemize}\itemsep=0pt
+\item Left-click on the required object on the palette, then left-click on the diagram window.
+\end{itemize}
+
+
+% This section commented out
+\begin{comment}
+\bibliography{refs}
+\addcontentsline{toc}{chapter}{Bibliography}
+\setheader{{\it REFERENCES}}{}{}{}{}{{\it REFERENCES}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+\end{comment}
+
+\addcontentsline{toc}{chapter}{Index}
+\printindex%
+
+\setheader{{\it INDEX}}{}{}{}{}{{\it INDEX}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+\end{document}
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: project.cpp
+// Purpose: Studio project classes
+// Author: Julian Smart
+// Modified by:
+// Created: 27/7/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#include "wx/mdi.h"
+#endif
+
+#include "wx/laywin.h"
+#include "studio.h"
+#include "project.h"
+
+IMPLEMENT_CLASS(csProjectTreeCtrl, wxTreeCtrl)
+
+BEGIN_EVENT_TABLE(csProjectTreeCtrl, wxTreeCtrl)
+END_EVENT_TABLE()
+
+// Define my frame constructor
+csProjectTreeCtrl::csProjectTreeCtrl(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
+ long style):
+
+ wxTreeCtrl(parent, id, pos, size, style),
+ m_imageList(16, 16)
+{
+ m_imageList.Add(wxIcon("folder1"));
+ m_imageList.Add(wxIcon("file1"));
+
+ SetImageList(& m_imageList);
+}
+
+csProjectTreeCtrl::~csProjectTreeCtrl()
+{
+ SetImageList(NULL);
+}
+
+// Create the project window
+bool csApp::CreateProjectWindow(wxFrame *parent)
+{
+#if 0
+ // Create a layout window
+ wxSashLayoutWindow* win = new wxSashLayoutWindow(parent, ID_LAYOUT_WINDOW_PROJECT, wxDefaultPosition, wxSize(200, 30), wxNO_BORDER|wxSW_3D|wxCLIP_CHILDREN);
+ win->SetDefaultSize(wxSize(150, 10000));
+ win->SetOrientation(wxLAYOUT_VERTICAL);
+ win->SetAlignment(wxLAYOUT_LEFT);
+ win->SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
+ win->SetSashVisible(wxSASH_RIGHT, TRUE);
+ win->SetExtraBorderSize(5);
+
+ m_projectSashWindow = win;
+
+ m_projectTreeCtrl = new csProjectTreeCtrl(win, ID_WINDOW_PROJECT_TREE, wxDefaultPosition,
+ wxDefaultSize, wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT|wxDOUBLE_BORDER);
+
+ // For now, hide the window
+ m_projectSashWindow->Show(FALSE);
+#endif
+
+ return TRUE;
+}
+
+// Fill out the project tree control
+void csApp::FillProjectTreeCtrl()
+{
+#if 0
+ csProjectTreeCtrl& tree = *GetProjectTreeCtrl();
+
+ // Dummy data for now
+ long level0 = tree.InsertItem(0, "Applications", 0, 0);
+ long level1 = tree.InsertItem(level0, "Projects", 0, 0);
+ tree.InsertItem(level1, "project1", 1, 1);
+ tree.InsertItem(level1, "project2", 1, 1);
+#endif
+}
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: project.h
+// Purpose: Studio project classes
+// Author: Julian Smart
+// Modified by:
+// Created: 27/7/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _STUDIO_PROJECT_H_
+#define _STUDIO_PROJECT_H_
+
+#include <wx/treectrl.h>
+#include <wx/imaglist.h>
+
+/*
+ * This is the project tree control.
+ */
+
+class csProjectTreeCtrl: public wxTreeCtrl
+{
+
+DECLARE_CLASS(csProjectTreeCtrl)
+public:
+
+ csProjectTreeCtrl(wxWindow *parent, const wxWindowID id, const wxPoint& pos, const wxSize& size,
+ long style = wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT);
+
+ ~csProjectTreeCtrl();
+
+ wxImageList& GetImageList() const { return (wxImageList&) m_imageList; }
+protected:
+ wxImageList m_imageList;
+
+DECLARE_EVENT_TABLE()
+};
+
+#endif
+ // _STUDIO_PROJECT_H_
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: shapes.cpp
+// Purpose: Implements Studio shapes
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+// #pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include <wx/wxprec.h>
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+#if !wxUSE_DOC_VIEW_ARCHITECTURE
+#error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in wx_setup.h!
+#endif
+
+#include <wx/wxexpr.h>
+
+#include "studio.h"
+#include "doc.h"
+#include "shapes.h"
+#include "view.h"
+#include "basicp.h"
+#include "linesp.h"
+#include "cspalette.h"
+#include "dialogs.h"
+
+#define csSTANDARD_SHAPE_WIDTH 100
+
+IMPLEMENT_CLASS(csDiagram, wxDiagram)
+
+csDiagram::~csDiagram()
+{
+ DeleteAllShapes();
+}
+
+void csDiagram::Redraw(wxDC& dc)
+{
+ wxDiagram::Redraw(dc);
+
+ // Draw line crossings
+ wxLineCrossings lineCrossings;
+ lineCrossings.FindCrossings(*this);
+ lineCrossings.DrawCrossings(*this, dc);
+}
+
+/*
+ * csEvtHandler: an event handler class for all shapes
+ */
+
+IMPLEMENT_DYNAMIC_CLASS(csEvtHandler, wxShapeEvtHandler)
+
+csEvtHandler::csEvtHandler(wxShapeEvtHandler *prev, wxShape *shape, const wxString& lab):
+ wxShapeEvtHandler(prev, shape)
+{
+ m_label = lab;
+}
+
+csEvtHandler::~csEvtHandler()
+{
+}
+
+// Copy any event handler data
+void csEvtHandler::CopyData(wxShapeEvtHandler& copy)
+{
+ wxShapeEvtHandler::CopyData(copy);
+
+ csEvtHandler& csCopy = (csEvtHandler&) copy;
+ csCopy.m_label = m_label;
+}
+
+void csEvtHandler::OnLeftClick(double x, double y, int keys, int attachment)
+{
+ wxClientDC dc(GetShape()->GetCanvas());
+ GetShape()->GetCanvas()->PrepareDC(dc);
+
+ csDiagramView* view = ((csCanvas*)GetShape()->GetCanvas())->GetView();
+ view->ReflectPointSize(GetShape()->GetFont()->GetPointSize());
+
+ if (GetShape()->IsKindOf(CLASSINFO(wxLineShape)))
+ view->ReflectArrowState((wxLineShape*) GetShape());
+
+ csEditorToolPalette *palette = wxGetApp().GetDiagramPalette();
+ if (palette->GetSelection() == PALETTE_TEXT_TOOL)
+ {
+ view->ReflectPointSize(GetShape()->GetFont()->GetPointSize());
+
+ EditProperties();
+#if 0
+ csLabelEditingDialog* dialog = new csLabelEditingDialog(GetShape()->GetCanvas()->GetParent());
+ dialog->SetShapeLabel(m_label);
+ if (dialog->ShowModal() == wxID_CANCEL)
+ {
+ dialog->Destroy();
+ return;
+ }
+
+ wxString newLabel = dialog->GetShapeLabel();
+ dialog->Destroy();
+
+ wxShape* newShape = GetShape()->CreateNewCopy();
+
+ csEvtHandler* handler = (csEvtHandler *)newShape->GetEventHandler();
+ handler->m_label = newLabel;
+
+ view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Edit label", (csDiagramDocument*) view->GetDocument(),
+ new csCommandState(ID_CS_EDIT_PROPERTIES, newShape, GetShape())));
+#endif
+ return;
+ }
+
+ if (keys == 0)
+ {
+ // If no shift key, then everything is deselected.
+ // If the shape was selected, deselect it and vice versa.
+ bool selected = GetShape()->Selected();
+
+ view->SelectAll(FALSE);
+
+ selected = !selected;
+
+ GetShape()->Select(selected, &dc);
+ GetShape()->GetCanvas()->Redraw(dc); // Redraw because bits of objects will be missing
+
+ view->SelectShape(GetShape(), selected);
+ }
+ else if (keys & KEY_SHIFT)
+ {
+ if (GetShape()->Selected())
+ {
+ GetShape()->Select(FALSE, &dc);
+ view->SelectShape(GetShape(), FALSE);
+ }
+ else
+ {
+ GetShape()->Select(TRUE, &dc);
+ view->SelectShape(GetShape(), TRUE);
+ }
+ GetShape()->GetCanvas()->Redraw(dc); // Redraw because bits of objects will be missing
+ }
+ else if (keys & KEY_CTRL)
+ {
+ // Do something for CONTROL
+ }
+ else
+ {
+ ((wxFrame*)wxGetApp().GetTopWindow())->SetStatusText(m_label);
+ }
+}
+
+void csEvtHandler::OnRightClick(double x, double y, int keys, int attachment)
+{
+ // Have to convert back to physical coordinates from logical coordinates.
+
+ int viewStartX, viewStartY;
+ int unitX, unitY;
+ GetShape()->GetCanvas()->ViewStart(& viewStartX, & viewStartY);
+ GetShape()->GetCanvas()->GetScrollPixelsPerUnit(& unitX, & unitY);
+
+ int x1 = (int)(x * GetShape()->GetCanvas()->GetScaleX());
+ int y1 = (int)(y * GetShape()->GetCanvas()->GetScaleY());
+
+ int menuX = (int) (x1 - (viewStartX * unitX)) ;
+ int menuY = (int) (y1 - (viewStartY * unitY));
+
+ wxGetApp().GetShapeEditMenu()->SetClientData((char*) GetShape());
+ wxGetApp().GetShapeEditMenu()->Enable(ID_CS_ROTATE_CLOCKWISE, !GetShape()->IsKindOf(CLASSINFO(wxLineShape)));
+ wxGetApp().GetShapeEditMenu()->Enable(ID_CS_ROTATE_ANTICLOCKWISE, !GetShape()->IsKindOf(CLASSINFO(wxLineShape)));
+
+ GetShape()->GetCanvas()->PopupMenu(wxGetApp().GetShapeEditMenu(), menuX, menuY);
+}
+
+/*
+ * Implement connection of two shapes by right-dragging between them.
+ */
+
+void csEvtHandler::OnBeginDragRight(double x, double y, int keys, int attachment)
+{
+ wxClientDC dc(GetShape()->GetCanvas());
+ GetShape()->GetCanvas()->PrepareDC(dc);
+
+ wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
+ dc.SetLogicalFunction(wxXOR);
+ dc.SetPen(dottedPen);
+ double xp, yp;
+ GetShape()->GetAttachmentPositionEdge(attachment, &xp, &yp);
+ dc.DrawLine(xp, yp, x, y);
+ GetShape()->GetCanvas()->CaptureMouse();
+}
+
+void csEvtHandler::OnDragRight(bool draw, double x, double y, int keys, int attachment)
+{
+ wxClientDC dc(GetShape()->GetCanvas());
+ GetShape()->GetCanvas()->PrepareDC(dc);
+
+ wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
+ dc.SetLogicalFunction(wxXOR);
+ dc.SetPen(dottedPen);
+ double xp, yp;
+ GetShape()->GetAttachmentPositionEdge(attachment, &xp, &yp);
+ dc.DrawLine(xp, yp, x, y);
+}
+
+void csEvtHandler::OnEndDragRight(double x, double y, int keys, int attachment)
+{
+ GetShape()->GetCanvas()->ReleaseMouse();
+ csCanvas *canvas = (csCanvas *)GetShape()->GetCanvas();
+
+ // Check if we're on an object
+ int new_attachment;
+ wxShape *otherShape = canvas->FindFirstSensitiveShape(x, y, &new_attachment, OP_DRAG_RIGHT);
+
+ if (otherShape && !otherShape->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ wxLineShape* theShape = new csLineShape;
+
+ theShape->AssignNewIds();
+ theShape->SetEventHandler(new csEvtHandler(theShape, theShape, wxString("")));
+ theShape->SetPen(wxBLACK_PEN);
+ theShape->SetBrush(wxRED_BRUSH);
+
+ wxToolBar* toolbar = wxGetApp().GetDiagramToolBar();
+ bool haveArrow = toolbar->GetToolState(DIAGRAM_TOOLBAR_LINE_ARROW);
+
+ wxLineShape *lineShape = (wxLineShape *)theShape;
+
+ // Yes, you can have more than 2 control points, in which case
+ // it becomes a multi-segment line.
+ lineShape->MakeLineControlPoints(2);
+
+ if (haveArrow)
+ lineShape->AddArrow(ARROW_ARROW, ARROW_POSITION_MIDDLE, 10.0, 0.0, "Normal arrowhead");
+
+ lineShape->SetFrom(GetShape());
+ lineShape->SetTo(otherShape);
+ lineShape->SetAttachments(attachment, new_attachment);
+
+ canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(
+ new csDiagramCommand("Line", (csDiagramDocument *)canvas->GetView()->GetDocument(),
+ new csCommandState(ID_CS_ADD_LINE, lineShape, NULL)));
+ }
+}
+
+static double g_DragOffsetX = 0.0;
+static double g_DragOffsetY = 0.0;
+static double g_DragStartX = 0.0;
+static double g_DragStartY = 0.0;
+
+void csEvtHandler::OnDragLeft(bool draw, double x, double y, int keys, int attachment)
+{
+ if ((GetShape()->GetSensitivityFilter() & OP_DRAG_LEFT) != OP_DRAG_LEFT)
+ {
+ attachment = 0;
+ double dist;
+ if (GetShape()->GetParent())
+ {
+ GetShape()->GetParent()->HitTest(x, y, &attachment, &dist);
+ GetShape()->GetParent()->GetEventHandler()->OnDragLeft(draw, x, y, keys, attachment);
+ }
+ return;
+ }
+
+ wxClientDC dc(GetShape()->GetCanvas());
+ GetShape()->GetCanvas()->PrepareDC(dc);
+
+ dc.SetLogicalFunction(wxXOR);
+
+ wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
+ dc.SetPen(dottedPen);
+ dc.SetBrush(* wxTRANSPARENT_BRUSH);
+
+ double xx, yy;
+ xx = x + g_DragOffsetX;
+ yy = y + g_DragOffsetY;
+
+ GetShape()->GetCanvas()->Snap(&xx, &yy);
+
+ double offsetX = xx - g_DragStartX;
+ double offsetY = yy - g_DragStartY;
+
+// m_xpos = xx; m_ypos = yy;
+ double w, h;
+ GetShape()->GetBoundingBoxMax(&w, &h);
+ GetShape()->GetEventHandler()->OnDrawOutline(dc, xx, yy, w, h);
+
+ // Draw bounding box for other selected shapes
+ wxNode* node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (shape->Selected() && !shape->IsKindOf(CLASSINFO(wxLineShape)) && (shape != GetShape()))
+ {
+ shape->GetBoundingBoxMax(&w, &h);
+ shape->OnDrawOutline(dc, shape->GetX() + offsetX, shape->GetY() + offsetY, w, h);
+ }
+ node = node->Next();
+ }
+}
+
+void csEvtHandler::OnBeginDragLeft(double x, double y, int keys, int attachment)
+{
+ if ((GetShape()->GetSensitivityFilter() & OP_DRAG_LEFT) != OP_DRAG_LEFT)
+ {
+ attachment = 0;
+ double dist;
+ if (GetShape()->GetParent())
+ {
+ GetShape()->GetParent()->HitTest(x, y, &attachment, &dist);
+ GetShape()->GetParent()->GetEventHandler()->OnBeginDragLeft(x, y, keys, attachment);
+ }
+ return;
+ }
+
+ wxClientDC dc(GetShape()->GetCanvas());
+ GetShape()->GetCanvas()->PrepareDC(dc);
+
+ // New policy: don't erase shape until end of drag.
+// Erase(dc);
+
+ g_DragOffsetX = GetShape()->GetX() - x;
+ g_DragOffsetY = GetShape()->GetY() - y;
+
+ double xx, yy;
+ xx = x + g_DragOffsetX;
+ yy = y + g_DragOffsetY;
+
+ GetShape()->GetCanvas()->Snap(&xx, &yy);
+
+ g_DragStartX = GetShape()->GetX();
+ g_DragStartY = GetShape()->GetY();
+
+ double offsetX = xx - g_DragStartX;
+ double offsetY = yy - g_DragStartY;
+
+ dc.SetLogicalFunction(wxXOR);
+
+ wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
+ dc.SetPen(dottedPen);
+ dc.SetBrush((* wxTRANSPARENT_BRUSH));
+
+ double w, h;
+ GetShape()->GetBoundingBoxMax(&w, &h);
+ GetShape()->GetEventHandler()->OnDrawOutline(dc, xx, yy, w, h);
+
+ // Draw bounding box for other selected shapes
+ wxNode* node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (shape->Selected() && !shape->IsKindOf(CLASSINFO(wxLineShape)) && (shape != GetShape()))
+ {
+ shape->GetBoundingBoxMax(&w, &h);
+ shape->OnDrawOutline(dc, shape->GetX() + offsetX, shape->GetY() + offsetY, w, h);
+ }
+ node = node->Next();
+ }
+
+ GetShape()->GetCanvas()->CaptureMouse();
+}
+
+
+void csEvtHandler::OnEndDragLeft(double x, double y, int keys, int attachment)
+{
+ csCanvas *canvas = (csCanvas *)GetShape()->GetCanvas();
+
+ canvas->ReleaseMouse();
+ if ((GetShape()->GetSensitivityFilter() & OP_DRAG_LEFT) != OP_DRAG_LEFT)
+ {
+ attachment = 0;
+ double dist;
+ if (GetShape()->GetParent())
+ {
+ GetShape()->GetParent()->HitTest(x, y, &attachment, &dist);
+ GetShape()->GetParent()->GetEventHandler()->OnEndDragLeft(x, y, keys, attachment);
+ }
+ return;
+ }
+
+ wxClientDC dc(canvas);
+ canvas->PrepareDC(dc);
+
+ dc.SetLogicalFunction(wxCOPY);
+
+ double xx = x + g_DragOffsetX;
+ double yy = y + g_DragOffsetY;
+
+ canvas->Snap(&xx, &yy);
+
+ double offsetX = xx - g_DragStartX;
+ double offsetY = yy - g_DragStartY;
+
+ wxShape* newShape = GetShape()->CreateNewCopy();
+
+ newShape->SetX(xx);
+ newShape->SetY(yy);
+
+ csDiagramCommand* cmd = new csDiagramCommand("Move", (csDiagramDocument*)canvas->GetView()->GetDocument(),
+ new csCommandState(ID_CS_MOVE, newShape, GetShape()));
+
+ // Move line points
+ wxNode* node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ // Only move the line point(s) if both ends move too
+ if (shape->IsKindOf(CLASSINFO(wxLineShape)) &&
+ ((wxLineShape*)shape)->GetTo()->Selected() && ((wxLineShape*)shape)->GetFrom()->Selected())
+ {
+ wxLineShape* lineShape = (wxLineShape*) shape;
+
+ if (lineShape->GetLineControlPoints()->Number() > 2)
+ {
+ wxLineShape* newLineShape = (wxLineShape*) lineShape->CreateNewCopy();
+
+ wxNode *node1 = newLineShape->GetLineControlPoints()->First();
+ while (node1)
+ {
+ wxRealPoint *point = (wxRealPoint *)node1->Data();
+ point->x += offsetX;
+ point->y += offsetY;
+ node1 = node1->Next();
+ }
+ cmd->AddState(new csCommandState(ID_CS_MOVE_LINE_POINT, newLineShape, lineShape));
+ lineShape->Erase(dc);
+ }
+ }
+ node = node->Next();
+ }
+
+ // Add other selected node shapes, if any
+ node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (shape->Selected() && !shape->IsKindOf(CLASSINFO(wxLineShape)) && (shape != GetShape()))
+ {
+ wxShape* newShape2 = shape->CreateNewCopy();
+ newShape2->SetX(shape->GetX() + offsetX);
+ newShape2->SetY(shape->GetY() + offsetY);
+ cmd->AddState(new csCommandState(ID_CS_MOVE, newShape2, shape));
+ }
+ node = node->Next();
+ }
+
+ canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd);
+}
+
+void csEvtHandler::OnSizingEndDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
+{
+ wxShape* shape = GetShape();
+ csCanvas *canvas = (csCanvas *)GetShape()->GetCanvas();
+
+ if (shape->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ // TODO: Do/Undo support for line operations
+ ((wxLineShape*)shape)->wxLineShape::OnSizingEndDragLeft(pt, x, y, keys, attachment);
+#if 0
+ wxLineShape* lineShape = (wxLineShape*) shape;
+
+ wxLineControlPoint* lpt = (wxLineControlPoint*) pt;
+
+ wxClientDC dc(canvas);
+ canvas->PrepareDC(dc);
+
+ shape->SetDisableLabel(FALSE);
+
+ if (lpt->m_type == CONTROL_POINT_LINE)
+ {
+ canvas->Snap(&x, &y);
+
+ dc.SetLogicalFunction(wxCOPY);
+ lpt->SetX(x); lpt->SetY(y);
+ lpt->m_point->x = x; lpt->m_point->y = y;
+
+ this->OnMoveLink(dc);
+ }
+ if (lpt->m_type == CONTROL_POINT_ENDPOINT_FROM)
+ {
+ if (lpt->m_oldCursor)
+ canvas->SetCursor(lpt->m_oldCursor);
+ lineShape->Erase(dc);
+
+ lpt->SetX(x); lpt->SetY(y);
+
+ if (lineShape->GetFrom())
+ {
+ lineShape->GetFrom()->MoveLineToNewAttachment(dc, lineShape, x, y);
+ }
+ }
+ if (lpt->m_type == CONTROL_POINT_ENDPOINT_TO)
+ {
+ if (lpt->m_oldCursor)
+ canvas->SetCursor(lpt->m_oldCursor);
+
+ lpt->SetX(x); lpt->SetY(y);
+
+ if (lineShape->GetTo())
+ {
+ lineShape->GetTo()->MoveLineToNewAttachment(dc, lineShape, x, y);
+ }
+ }
+#endif
+ return;
+ }
+
+ wxClientDC dc(canvas);
+ canvas->PrepareDC(dc);
+
+ canvas->ReleaseMouse();
+ dc.SetLogicalFunction(wxCOPY);
+
+// shape->Erase(dc);
+/*
+ shape->Recompute();
+ shape->ResetControlPoints();
+ if (!pt->m_eraseObject)
+ shape->Show(FALSE);
+*/
+
+ wxShape* newShape = shape->CreateNewCopy();
+
+ if (newShape->IsKindOf(CLASSINFO(wxPolygonShape)))
+ {
+ wxPolygonControlPoint* ppt = (wxPolygonControlPoint*) pt;
+ newShape->SetSize(ppt->GetNewSize().x, ppt->GetNewSize().y);
+
+ ((wxPolygonShape *)newShape)->CalculateBoundingBox();
+ ((wxPolygonShape *)newShape)->CalculatePolygonCentre();
+ newShape->ResetControlPoints();
+ }
+ else
+ {
+ newShape->SetSize(pt->sm_controlPointDragEndWidth, pt->sm_controlPointDragEndHeight);
+ if (shape->GetCentreResize())
+ {
+ // Old position is fine
+ }
+ else
+ {
+ newShape->SetX(pt->sm_controlPointDragPosX);
+ newShape->SetY(pt->sm_controlPointDragPosY);
+ }
+ }
+
+ csDiagramCommand* cmd = new csDiagramCommand("Size", (csDiagramDocument*)canvas->GetView()->GetDocument(),
+ new csCommandState(ID_CS_SIZE, newShape, shape));
+
+ canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd);
+
+}
+
+void csEvtHandler::OnEndSize(double x, double y)
+{
+ wxClientDC dc(GetShape()->GetCanvas());
+ GetShape()->GetCanvas()->PrepareDC(dc);
+
+ GetShape()->FormatText(dc, m_label);
+}
+
+void csEvtHandler::OnChangeAttachment(int attachment, wxLineShape* line, wxList& ordering)
+{
+ csCanvas *canvas = (csCanvas *)GetShape()->GetCanvas();
+
+ // We actually submit two different states: one to change the ordering, and another
+ // to change the attachment for the line.
+ // Problem. If we refresh after the attachment change, we'll get a flicker.
+ // We really want to do both in a oner.
+
+ csDiagramCommand* cmd = new csDiagramCommand("Change attachment", (csDiagramDocument*)canvas->GetView()->GetDocument());
+
+ wxLineShape* newLine = (wxLineShape*) line->CreateNewCopy();
+ if (line->GetTo() == GetShape())
+ newLine->SetAttachmentTo(attachment);
+ else
+ newLine->SetAttachmentFrom(attachment);
+
+ cmd->AddState(new csCommandState(ID_CS_CHANGE_LINE_ATTACHMENT, newLine, line));
+
+ // Change ordering
+ wxShape* newShape = GetShape()->CreateNewCopy();
+ newShape->ApplyAttachmentOrdering(ordering);
+
+ cmd->AddState(new csCommandState(ID_CS_CHANGE_LINE_ORDERING, newShape, GetShape()));
+
+ canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd);
+}
+
+void csEvtHandler::OnLeftDoubleClick(double x, double y, int keys, int attachment)
+{
+ EditProperties();
+}
+
+// Popup up a property dialog
+bool csEvtHandler::EditProperties()
+{
+ wxShape* shape = GetShape();
+
+ // For now, no line property editing
+ if (shape->IsKindOf(CLASSINFO(wxLineShape)))
+ return FALSE;
+
+ csDiagramView* view = ((csCanvas*)shape->GetCanvas())->GetView();
+
+ wxPanel* attributeDialog;
+ wxString attributeDialogName;
+ wxString title;
+
+ if (shape->IsKindOf(CLASSINFO(csThinRectangleShape)))
+ {
+ attributeDialog = new csThinRectangleDialog;
+ attributeDialogName = "thin_rectangle";
+ title = "Thin Rectangle Properties";
+ }
+ else if (shape->IsKindOf(CLASSINFO(csWideRectangleShape)))
+ {
+ attributeDialog = new csWideRectangleDialog;
+ attributeDialogName = "wide_rectangle";
+ title = "Wide Rectangle Properties";
+ }
+ else if (shape->IsKindOf(CLASSINFO(csTriangleShape)))
+ {
+ attributeDialog = new csTriangleDialog;
+ attributeDialogName = "triangle";
+ title = "Triangle Properties";
+ }
+ else if (shape->IsKindOf(CLASSINFO(csSemiCircleShape)))
+ {
+ attributeDialog = new csSemiCircleDialog;
+ attributeDialogName = "semi_circle";
+ title = "Semicircle Properties";
+ }
+ else if (shape->IsKindOf(CLASSINFO(csCircleShape)))
+ {
+ attributeDialog = new csCircleDialog;
+ attributeDialogName = "circle";
+ title = "Circle Properties";
+ }
+ else if (shape->IsKindOf(CLASSINFO(csCircleShadowShape)))
+ {
+ attributeDialog = new csCircleShadowDialog;
+ attributeDialogName = "circle_shadow";
+ title = "Circle Shadow Properties";
+ }
+ else if (shape->IsKindOf(CLASSINFO(csTextBoxShape)))
+ {
+ attributeDialog = new csTextBoxDialog;
+ attributeDialogName = "text_box";
+ title = "Text Box Properties";
+ }
+ else if (shape->IsKindOf(CLASSINFO(csGroupShape)))
+ {
+ attributeDialog = new csGroupDialog;
+ attributeDialogName = "group";
+ title = "Group Properties";
+ }
+ else if (shape->IsKindOf(CLASSINFO(csOctagonShape)))
+ {
+ attributeDialog = new csOctagonDialog;
+ attributeDialogName = "octagon";
+ title = "Octagon Properties";
+ }
+ else
+ {
+ wxMessageBox("Unrecognised shape.", "Studio", wxICON_EXCLAMATION);
+ return FALSE;
+ }
+
+ csShapePropertiesDialog* dialog = new csShapePropertiesDialog(shape->GetCanvas()->GetParent(), title, attributeDialog, attributeDialogName);
+ dialog->GetGeneralPropertiesDialog()->SetShapeLabel(m_label);
+ if (dialog->ShowModal() == wxID_CANCEL)
+ {
+ dialog->Destroy();
+ return FALSE;
+ }
+
+ wxString newLabel = dialog->GetGeneralPropertiesDialog()->GetShapeLabel();
+ dialog->Destroy();
+
+ wxShape* newShape = shape->CreateNewCopy();
+
+ csEvtHandler* handler2 = (csEvtHandler *)newShape->GetEventHandler();
+ handler2->m_label = newLabel;
+
+ view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Edit properties", (csDiagramDocument*) view->GetDocument(),
+ new csCommandState(ID_CS_EDIT_PROPERTIES, newShape, shape)));
+
+ return TRUE;
+}
+
+/*
+ * Diagram
+ */
+
+bool csDiagram::OnShapeSave(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
+{
+ wxDiagram::OnShapeSave(db, shape, expr);
+ csEvtHandler *handler = (csEvtHandler *)shape.GetEventHandler();
+ expr.AddAttributeValueString("label", handler->m_label);
+ return TRUE;
+}
+
+bool csDiagram::OnShapeLoad(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
+{
+ wxDiagram::OnShapeLoad(db, shape, expr);
+ wxString label("");
+ expr.GetAttributeValue("label", label);
+ csEvtHandler *handler = new csEvtHandler(&shape, &shape, label);
+ shape.SetEventHandler(handler);
+
+ return TRUE;
+}
+
+IMPLEMENT_DYNAMIC_CLASS(csThinRectangleShape, wxDrawnShape)
+
+csThinRectangleShape::csThinRectangleShape()
+{
+ SetDrawnPen(wxBLACK_PEN);
+ wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
+ SetDrawnBrush(brush);
+
+ double w = csSTANDARD_SHAPE_WIDTH/2;
+ double h = csSTANDARD_SHAPE_WIDTH;
+
+ DrawRectangle(wxRect(- w/2, - h/2, w, h));
+ CalculateSize();
+
+ SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
+ SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
+ SetCentreResize(FALSE);
+}
+
+IMPLEMENT_DYNAMIC_CLASS(csWideRectangleShape, wxDrawnShape)
+
+csWideRectangleShape::csWideRectangleShape()
+{
+ SetDrawnPen(wxBLACK_PEN);
+ wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
+ SetDrawnBrush(brush);
+
+ double w = csSTANDARD_SHAPE_WIDTH;
+ double h = w/2.0;
+
+ DrawRoundedRectangle(wxRect(- w/2, - h/2, w, h), -0.3);
+ CalculateSize();
+
+ SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
+ SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
+ SetCentreResize(FALSE);
+}
+
+IMPLEMENT_DYNAMIC_CLASS(csTriangleShape, wxDrawnShape)
+
+csTriangleShape::csTriangleShape()
+{
+ SetDrawnPen(wxBLACK_PEN);
+ wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
+ SetDrawnBrush(brush);
+
+ double w = csSTANDARD_SHAPE_WIDTH;
+ double h = (csSTANDARD_SHAPE_WIDTH*2.0)/3.0;
+
+ // Triangle, from top vertex
+ wxPoint* points = new wxPoint[3];
+
+
+ points[0] = wxPoint( 0 , - h / 2 );
+ points[1] = wxPoint( w / 2 , h / 2 );
+ points[2] = wxPoint( -w / 2, h / 2 );
+
+ DrawPolygon(3, points, oglMETAFLAGS_OUTLINE);
+
+ delete[] points;
+
+ // Add another triangle at the top for the black bit
+ SetDrawnBrush(wxBLACK_BRUSH);
+
+ points = new wxPoint[3];
+
+ // Calculate where the new points will be, using the proportions
+ // of the triangle.
+ double h1 = 8; // Height of little triangle.
+
+ /*
+ Formula: ((w/2) / h) = w1 / h1
+ w1 = ((w/2) / h) * h1;
+ */
+ double ratio = ((w/2.0) / h) ;
+ double w1 = ratio * h1;
+
+ points[0] = wxPoint(0 , (int) (- h / 2 ));
+ points[1] = wxPoint( (int) w1, (int) (- h / 2 + h1));
+ points[2] = wxPoint( (int) -w1, (int) (- h / 2 + h1));
+
+ DrawPolygon(3, points);
+
+ delete[] points;
+
+ CalculateSize();
+
+ SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
+ SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
+ SetCentreResize(FALSE);
+}
+
+IMPLEMENT_DYNAMIC_CLASS(csSemiCircleShape, wxDrawnShape)
+
+csSemiCircleShape::csSemiCircleShape()
+{
+ // Zero degrees
+ DrawAtAngle(oglDRAWN_ANGLE_0);
+
+ double w = csSTANDARD_SHAPE_WIDTH;
+ double h = w/2.0;
+
+ SetDrawnPen(wxTRANSPARENT_PEN);
+ SetDrawnBrush(wxTRANSPARENT_BRUSH);
+
+ // Draw a dummy rectangle that will be used for calculating the
+ // bounding box, since we can't calculate the bounding box for
+ // an arbitrary arc (not implemented)
+
+ DrawRectangle(wxRect(-w/2.0, -h/2.0, w, h));
+
+ SetDrawnPen(wxBLACK_PEN);
+ wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
+ SetDrawnBrush(brush);
+
+ DrawEllipticArc(wxRect(-w/2, -h/2, w, 2*h), 0.0, 180.0);
+ DrawLine(wxPoint(-w/2, h/2), wxPoint(w/2, h/2));
+
+ CalculateSize();
+
+ /// 90 degrees
+
+ w = csSTANDARD_SHAPE_WIDTH/2;
+ h = csSTANDARD_SHAPE_WIDTH;
+
+ DrawAtAngle(oglDRAWN_ANGLE_90);
+
+ SetDrawnPen(wxTRANSPARENT_PEN);
+ SetDrawnBrush(wxTRANSPARENT_BRUSH);
+
+ DrawRectangle(wxRect(-w/2, -h/2, w, h));
+
+ SetDrawnPen(wxBLACK_PEN);
+ SetDrawnBrush(brush);
+
+ DrawEllipticArc(wxRect(-w/2 - w, -h/2, 2*w, h), 270.0, 90.0);
+ DrawLine(wxPoint(-w/2, -h/2), wxPoint(-w/2, h/2));
+
+ CalculateSize();
+
+ /// 180 degrees
+
+ DrawAtAngle(oglDRAWN_ANGLE_180);
+
+ w = csSTANDARD_SHAPE_WIDTH;
+ h = csSTANDARD_SHAPE_WIDTH/2;
+
+ SetDrawnPen(wxTRANSPARENT_PEN);
+ SetDrawnBrush(wxTRANSPARENT_BRUSH);
+
+ DrawRectangle(wxRect(-w/2, -h/2, w, h));
+
+ SetDrawnPen(wxBLACK_PEN);
+ SetDrawnBrush(brush);
+
+ DrawEllipticArc(wxRect(-w/2, -h/2 - h, w, 2*h), 180.0, 0.0);
+ DrawLine(wxPoint(-w/2, -h/2), wxPoint(w/2, -h/2));
+
+ CalculateSize();
+
+ /// 270 degrees
+
+ DrawAtAngle(oglDRAWN_ANGLE_270);
+
+ w = csSTANDARD_SHAPE_WIDTH/2;
+ h = csSTANDARD_SHAPE_WIDTH;
+
+ SetDrawnPen(wxTRANSPARENT_PEN);
+ SetDrawnBrush(wxTRANSPARENT_BRUSH);
+
+ DrawRectangle(wxRect(-w/2, -h/2, w, h));
+
+ SetDrawnPen(wxBLACK_PEN);
+ SetDrawnBrush(brush);
+
+ DrawEllipticArc(wxRect(-w/2, -h/2, 2*w, h), 90.0, 270.0);
+ DrawLine(wxPoint(w/2, -h/2), wxPoint(w/2, h/2));
+
+ CalculateSize();
+
+ // Reset to zero
+ DrawAtAngle(oglDRAWN_ANGLE_0);
+ CalculateSize();
+
+ SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
+ SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
+ SetCentreResize(FALSE);
+}
+
+IMPLEMENT_DYNAMIC_CLASS(csCircleShape, wxCircleShape)
+
+csCircleShape::csCircleShape()
+{
+ SetPen(wxBLACK_PEN);
+ wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
+ SetBrush(brush);
+
+ SetSize(csSTANDARD_SHAPE_WIDTH*0.6, csSTANDARD_SHAPE_WIDTH*0.6);
+
+ SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
+ SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
+ SetCentreResize(FALSE);
+}
+
+IMPLEMENT_DYNAMIC_CLASS(csCircleShadowShape, wxCircleShape)
+
+csCircleShadowShape::csCircleShadowShape()
+{
+ SetPen(wxBLACK_PEN);
+ wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
+ SetBrush(brush);
+
+ SetSize(csSTANDARD_SHAPE_WIDTH*0.6, csSTANDARD_SHAPE_WIDTH*0.6);
+
+ SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
+ SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
+ SetCentreResize(FALSE);
+ SetShadowMode(SHADOW_RIGHT);
+}
+
+IMPLEMENT_DYNAMIC_CLASS(csOctagonShape, wxPolygonShape)
+
+csOctagonShape::csOctagonShape()
+{
+ SetPen(wxBLACK_PEN);
+ SetBrush(wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID));
+
+ double w = csSTANDARD_SHAPE_WIDTH*0.5;
+ double h = csSTANDARD_SHAPE_WIDTH*0.5;
+
+ double prop = h/3.0;
+
+ wxList* points = new wxList;
+ points->Append((wxObject*) new wxRealPoint(-w/2.0 + prop, -h/2.0));
+ points->Append((wxObject*) new wxRealPoint(w/2.0 - prop, -h/2.0));
+ points->Append((wxObject*) new wxRealPoint(w/2.0, -h/2.0 + prop));
+ points->Append((wxObject*) new wxRealPoint(w/2.0, h/2.0 - prop));
+ points->Append((wxObject*) new wxRealPoint(w/2.0 - prop, h/2.0));
+ points->Append((wxObject*) new wxRealPoint(-w/2.0 + prop, h/2.0));
+ points->Append((wxObject*) new wxRealPoint(-w/2.0, h/2.0 - prop));
+ points->Append((wxObject*) new wxRealPoint(-w/2.0, -h/2.0 + prop));
+
+ Create(points);
+
+ SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
+ SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
+ SetCentreResize(FALSE);
+}
+
+// This is a transparent shape for drawing around other shapes.
+IMPLEMENT_DYNAMIC_CLASS(csGroupShape, wxRectangleShape)
+
+csGroupShape::csGroupShape()
+{
+ SetPen(wxThePenList->FindOrCreatePen("BLACK", 1, wxDOT));
+ SetBrush(wxTRANSPARENT_BRUSH);
+
+ SetSize(csSTANDARD_SHAPE_WIDTH, csSTANDARD_SHAPE_WIDTH);
+ SetCentreResize(FALSE);
+}
+
+void csGroupShape::OnDraw(wxDC& dc)
+{
+ wxRectangleShape::OnDraw(dc);
+}
+
+// Must modify the hit-test so it doesn't obscure shapes that are inside.
+bool csGroupShape::HitTest(double x, double y, int* attachment, double* distance)
+{
+ *attachment = 0;
+ *distance = 0.0;
+
+ double width = 0.0, height = 0.0;
+ GetBoundingBoxMin(&width, &height);
+
+ double x1 = GetX() - (width/2.0);
+ double y1 = GetY() - (height/2.0);
+ double x2 = GetX() + (width/2.0);
+ double y2 = GetY() + (height/2.0);
+
+ double edgeTolerance = 4.0;
+
+ // Test each edge in turn
+
+ // Top/bottom edges
+ if (x >= x1 && x <= x2)
+ {
+ if ((y >= y1 - edgeTolerance) && (y <= y1 + edgeTolerance))
+ return TRUE;
+ if ((y <= y2 + edgeTolerance) && (y >= y2 - edgeTolerance))
+ return TRUE;
+ }
+ // Left/right edges
+ if (y >= y1 && y <= y2)
+ {
+ if ((x >= x1 - edgeTolerance) && (x <= x1 + edgeTolerance))
+ return TRUE;
+ if ((x <= x2 + edgeTolerance) && (x >= x2 - edgeTolerance))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+IMPLEMENT_DYNAMIC_CLASS(csTextBoxShape, wxRectangleShape)
+
+csTextBoxShape::csTextBoxShape()
+{
+ SetPen(wxTRANSPARENT_PEN);
+ SetBrush(wxTRANSPARENT_BRUSH);
+
+ SetSize(csSTANDARD_SHAPE_WIDTH, csSTANDARD_SHAPE_WIDTH/2.0);
+
+ SetAttachmentMode(ATTACHMENT_MODE_NONE);
+ SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
+ SetCentreResize(FALSE);
+}
+
+IMPLEMENT_DYNAMIC_CLASS(csLineShape, wxLineShape)
+
+csLineShape::csLineShape()
+{
+}
+
+bool csLineShape::OnMoveMiddleControlPoint(wxDC& dc, wxLineControlPoint* lpt, const wxRealPoint& pt)
+{
+ csDiagramView* view = ((csCanvas*)GetCanvas())->GetView();
+
+ // Temporarily set the new shape properties so we can copy it
+ lpt->SetX(pt.x); lpt->SetY(pt.y);
+ lpt->m_point->x = pt.x; lpt->m_point->y = pt.y;
+
+ wxLineShape* newShape = (wxLineShape*) this->CreateNewCopy();
+
+ // Now set them back again
+ lpt->SetX(lpt->m_originalPos.x); lpt->SetY(lpt->m_originalPos.y);
+ lpt->m_point->x = lpt->m_originalPos.x; lpt->m_point->y = lpt->m_originalPos.y;
+
+ view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Move line point", (csDiagramDocument*) view->GetDocument(),
+ new csCommandState(ID_CS_MOVE_LINE_POINT, newShape, this)));
+
+ return TRUE;
+}
+
+wxLabelShape* csLineShape::OnCreateLabelShape(wxLineShape *parent, wxShapeRegion *region, double w, double h)
+{
+ return new csLabelShape(parent, region, w, h);
+}
+
+#if 0
+bool csLineShape::OnLabelMovePre(wxDC& dc, wxLabelShape* labelShape, double x, double y, double old_x, double old_y, bool display)
+{
+ csDiagramView* view = ((csCanvas*)GetCanvas())->GetView();
+
+ wxLineShape* newShape = (wxLineShape*) this->CreateNewCopy();
+
+ wxLineShape::OnLabelMovePre(dc, labelShape, x, y, old_x, old_y, display);
+
+ view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Move label", (csDiagramDocument*) view->GetDocument(),
+ new csCommandState(ID_CS_MOVE_LABEL, newShape, this)));
+ return TRUE;
+}
+#endif
+
+IMPLEMENT_DYNAMIC_CLASS(csLabelShape, wxLabelShape)
+
+csLabelShape::csLabelShape(wxLineShape *parent, wxShapeRegion *region, double w, double h):
+ wxLabelShape(parent, region, w, h)
+{
+}
+
+// TODO: not sure how intercept normal behaviour (OnMovePre) to make
+// label movement undo-able.
+void csLabelShape::OnEndDragLeft(double x, double y, int keys, int attachment)
+{
+ wxLabelShape::OnEndDragLeft(x, y, keys, attachment);
+}
+
+
+// Menu for editing shapes
+void studioShapeEditProc(wxMenu& menu, wxCommandEvent& event)
+{
+ wxShape* shape = (wxShape*) menu.GetClientData();
+ csDiagramView* view = ((csCanvas*)shape->GetCanvas())->GetView();
+
+ switch (event.GetId())
+ {
+ case ID_CS_EDIT_PROPERTIES:
+ {
+ csEvtHandler* handler1 = (csEvtHandler *)shape->GetEventHandler();
+ handler1->EditProperties();
+#if 0
+ csEvtHandler* handler1 = (csEvtHandler *)shape->GetEventHandler();
+ csLabelEditingDialog* dialog = new csLabelEditingDialog(shape->GetCanvas()->GetParent());
+ dialog->SetShapeLabel(handler1->m_label);
+ if (dialog->ShowModal() == wxID_CANCEL)
+ {
+ dialog->Destroy();
+ return;
+ }
+
+ wxString newLabel = dialog->GetShapeLabel();
+ dialog->Destroy();
+
+ wxShape* newShape = shape->CreateNewCopy();
+
+ csEvtHandler* handler2 = (csEvtHandler *)newShape->GetEventHandler();
+ handler2->m_label = newLabel;
+
+ view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Edit label", (csDiagramDocument*) view->GetDocument(),
+ new csCommandState(ID_CS_EDIT_LABEL, newShape, shape)));
+#endif
+ break;
+ }
+ case wxID_CUT:
+ {
+ wxList list;
+ list.Append(shape);
+ view->DoCut(list);
+ break;
+ }
+ case ID_CS_ROTATE_CLOCKWISE:
+ case ID_CS_ROTATE_ANTICLOCKWISE:
+ {
+ if (shape->IsKindOf(CLASSINFO(wxLineShape)))
+ break;
+
+ double theta = shape->GetRotation();
+ const double myPi = 3.1415926535897932384626433832795 ;
+ double ninetyDegrees = myPi/2.0;
+
+ wxString opStr;
+ if (event.GetId() == ID_CS_ROTATE_CLOCKWISE)
+ {
+ theta += ninetyDegrees;
+ opStr = "Rotate clockwise";
+ }
+ else
+ {
+ theta -= ninetyDegrees;
+ opStr = "Rotate anticlockwise";
+ }
+
+ if (theta >= 2.0*myPi || theta < 0.0)
+ theta = 0.0;
+ wxShape* newShape = shape->CreateNewCopy();
+ newShape->Rotate(0.0, 0.0, theta);
+ wxList newShapes;
+ wxList oldShapes;
+ newShapes.Append(newShape);
+ oldShapes.Append(shape);
+ view->DoCmd(newShapes, oldShapes, event.GetId(), opStr);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: shapes.h
+// Purpose: Shape classes
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _STUDIO_SHAPES_H_
+#define _STUDIO_SHAPES_H_
+
+#ifdef __GNUG__
+// #pragma interface
+#endif
+
+#include <wx/docview.h>
+#include <wx/string.h>
+#include <wx/wxexpr.h>
+
+#include "ogl.h"
+#include "basicp.h"
+#include "linesp.h"
+#include "drawn.h"
+
+class csDiagramDocument;
+
+/*
+ * Override a few members for this application
+ */
+
+class csDiagram: public wxDiagram
+{
+DECLARE_CLASS(csDiagram)
+public:
+ csDiagram(csDiagramDocument* doc) { m_doc = doc; }
+ ~csDiagram();
+ bool OnShapeSave(wxExprDatabase& db, wxShape& shape, wxExpr& expr);
+ bool OnShapeLoad(wxExprDatabase& db, wxShape& shape, wxExpr& expr);
+
+ inline csDiagramDocument* GetDocument() const { return m_doc; }
+ virtual void Redraw(wxDC& dc);
+
+protected:
+ csDiagramDocument* m_doc;
+};
+
+class wxDiagramClipboard: public wxDiagram
+{
+DECLARE_DYNAMIC_CLASS(wxDiagramClipboard)
+public:
+ wxDiagramClipboard() {}
+ ~wxDiagramClipboard() {}
+
+ // Copy selection to clipboard
+ bool Copy(wxDiagram* diagram);
+
+ // Copy contents to the diagram, with new ids.
+ // If dc is non-NULL, the pasted shapes will be selected.
+ // The offsets are used to place the shapes at a different position
+ // from the original (for example, for duplicating shapes).
+ bool Paste(wxDiagram* diagram, wxDC* dc = NULL,
+ int offsetX = 0, int offsetY = 0);
+
+#ifdef __WXMSW__
+ // Draw contents to a Windows metafile device context and bitmap, and then copy
+ // to the Windows clipboard.
+ bool CopyToClipboard(double scale);
+#endif
+
+// Overridables
+ // Start/end copying
+ virtual bool OnStartCopy(wxDiagram* diagramTo) { return TRUE; };
+ virtual bool OnEndCopy(wxDiagram* diagramTo) { return TRUE; };
+
+ // Override this to e.g. have the shape added through a Do/Undo command system.
+ // By default, we'll just add it directly to the destination diagram, and
+ // select the shape (if dc is non-NULL).
+ virtual bool OnAddShape(wxDiagram* diagramTo, wxShape* newShape, wxDC* dc);
+
+protected:
+ bool DoCopy(wxDiagram* diagramFrom, wxDiagram* diagramTo, bool newIds,
+ wxDC* dc, int offsetX = 0, int offsetY = 0);
+
+};
+
+class csDiagramCommand;
+
+class csDiagramClipboard: public wxDiagramClipboard
+{
+DECLARE_DYNAMIC_CLASS(csDiagramClipboard)
+public:
+ csDiagramClipboard() { m_currentCmd = NULL; }
+ ~csDiagramClipboard() {}
+
+ // Start/end copying
+ bool OnStartCopy(wxDiagram* diagramTo);
+ bool OnEndCopy(wxDiagram* diagramTo);
+
+ bool OnAddShape(wxDiagram* diagramTo, wxShape* newShape, wxDC* dc);
+
+protected:
+ csDiagramCommand* m_currentCmd;
+};
+
+
+/*
+ * The Studio shapes
+ * N.B. TODO: these should really all have another constructor
+ * for the ready-initialised shape, with the default one not having any
+ * data. Otherwise when copying a shape, you have to delete the old data
+ * first -> slightly less efficient. The initialised shapes are only required
+ * for the first creation of the shape in the palette, everything else is copied.
+ */
+
+class csThinRectangleShape: public wxDrawnShape
+{
+DECLARE_DYNAMIC_CLASS(csThinRectangleShape)
+public:
+ csThinRectangleShape();
+};
+
+class csWideRectangleShape: public wxDrawnShape
+{
+DECLARE_DYNAMIC_CLASS(csWideRectangleShape)
+public:
+ csWideRectangleShape();
+};
+
+class csTriangleShape: public wxDrawnShape
+{
+DECLARE_DYNAMIC_CLASS(csTriangleShape)
+public:
+ csTriangleShape();
+};
+
+class csSemiCircleShape: public wxDrawnShape
+{
+DECLARE_DYNAMIC_CLASS(csSemiCircleShape)
+public:
+ csSemiCircleShape();
+};
+
+class csCircleShape: public wxCircleShape
+{
+DECLARE_DYNAMIC_CLASS(csCircleShape)
+public:
+ csCircleShape();
+};
+
+class csCircleShadowShape: public wxCircleShape
+{
+DECLARE_DYNAMIC_CLASS(csCircleShadowShape)
+public:
+ csCircleShadowShape();
+};
+
+class csOctagonShape: public wxPolygonShape
+{
+DECLARE_DYNAMIC_CLASS(csOctagonShape)
+public:
+ csOctagonShape();
+
+ // The attachments are as if it's a rectangle
+ bool GetAttachmentPosition(int attachment, double *x, double *y,
+ int nth = 0, int no_arcs = 1, wxLineShape *line = NULL)
+ { return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line); }
+ int GetNumberOfAttachments() const
+ { return wxShape::GetNumberOfAttachments(); }
+ bool AttachmentIsValid(int attachment) const
+ { return wxShape::AttachmentIsValid(attachment); }
+};
+
+// This is a transparent shape for drawing around other shapes.
+class csGroupShape: public wxRectangleShape
+{
+DECLARE_DYNAMIC_CLASS(csGroupShape)
+public:
+ csGroupShape();
+
+ void OnDraw(wxDC& dc);
+ // Must modify the hit-test so it doesn't obscure shapes that are inside.
+ bool HitTest(double x, double y, int* attachment, double* distance);
+};
+
+class csTextBoxShape: public wxRectangleShape
+{
+DECLARE_DYNAMIC_CLASS(csTextBoxShape)
+public:
+ csTextBoxShape();
+};
+
+class csLineShape: public wxLineShape
+{
+DECLARE_DYNAMIC_CLASS(csLineShape)
+public:
+ csLineShape();
+
+ virtual bool OnMoveMiddleControlPoint(wxDC& dc, wxLineControlPoint* lpt, const wxRealPoint& pt);
+ wxLabelShape* OnCreateLabelShape(wxLineShape *parent = NULL, wxShapeRegion *region = NULL, double w = 0.0, double h = 0.0);
+};
+
+/*
+ * Temporary arc label object
+ */
+
+class csLabelShape: public wxLabelShape
+{
+ DECLARE_DYNAMIC_CLASS(csLabelShape)
+
+ public:
+ csLabelShape(wxLineShape *parent = NULL, wxShapeRegion *region = NULL, double w = 0.0, double h = 0.0);
+
+ void OnEndDragLeft(double x, double y, int keys=0, int attachment = 0);
+};
+
+/*
+ * All shape event behaviour is routed through this handler, so we don't
+ * have to derive from each shape class. We plug this in to each shape.
+ */
+
+class csEvtHandler: public wxShapeEvtHandler
+{
+ DECLARE_DYNAMIC_CLASS(csEvtHandler)
+ public:
+ csEvtHandler(wxShapeEvtHandler *prev = NULL, wxShape *shape = NULL, const wxString& lab = "");
+ ~csEvtHandler();
+
+ void OnLeftClick(double x, double y, int keys = 0, int attachment = 0);
+ void OnRightClick(double x, double y, int keys = 0, int attachment = 0);
+ void OnBeginDragRight(double x, double y, int keys = 0, int attachment = 0);
+ void OnDragRight(bool draw, double x, double y, int keys = 0, int attachment = 0);
+ void OnEndDragRight(double x, double y, int keys = 0, int attachment = 0);
+ void OnEndSize(double x, double y);
+ void OnDragLeft(bool draw, double x, double y, int keys = 0, int attachment = 0);
+ void OnBeginDragLeft(double x, double y, int keys = 0, int attachment = 0);
+ void OnEndDragLeft(double x, double y, int keys = 0, int attachment = 0);
+ void OnSizingEndDragLeft(wxControlPoint* pt, double x, double y, int keys = 0, int attachment = 0);
+ void OnChangeAttachment(int attachment, wxLineShape* line, wxList& ordering);
+
+ void OnLeftDoubleClick(double x, double y, int keys = 0, int attachment = 0);
+
+ // Copy any event handler data
+ virtual void CopyData(wxShapeEvtHandler& copy);
+
+ // Popup up a property dialog
+ virtual bool EditProperties();
+
+public:
+ wxString m_label;
+};
+
+extern void studioShapeEditProc(wxMenu& menu, wxCommandEvent& event);
+
+#endif
+ // _STUDIO_SHAPES_H_
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: Studio.cpp
+// Purpose: Studio application class
+// Author: Julian Smart
+// Modified by:
+// Created: 27/7/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#include "wx/mdi.h"
+#endif
+
+#include "wx/resource.h"
+#include "wx/config.h"
+#include "wx/laywin.h"
+
+#ifdef __WXGTK__
+#include "folder.xpm"
+#endif
+
+#include "studio.h"
+#include "view.h"
+#include "doc.h"
+#include "mainfrm.h"
+#include "cspalette.h"
+#include "project.h"
+#include "symbols.h"
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__)
+#include "bitmaps/new.xpm"
+#include "bitmaps/open.xpm"
+#include "bitmaps/save.xpm"
+#include "bitmaps/copy.xpm"
+#include "bitmaps/cut.xpm"
+#include "bitmaps/paste.xpm"
+#include "bitmaps/print.xpm"
+#include "bitmaps/help.xpm"
+#include "bitmaps/undo.xpm"
+#include "bitmaps/redo.xpm"
+
+#include "bitmaps/alignl.xpm"
+#include "bitmaps/alignr.xpm"
+#include "bitmaps/alignt.xpm"
+#include "bitmaps/alignb.xpm"
+#include "bitmaps/horiz.xpm"
+#include "bitmaps/vert.xpm"
+#include "bitmaps/copysize.xpm"
+#include "bitmaps/linearrow.xpm"
+#include "bitmaps/newpoint.xpm"
+#include "bitmaps/cutpoint.xpm"
+#include "bitmaps/straight.xpm"
+
+#include "studio.xpm"
+#endif
+
+IMPLEMENT_APP(csApp)
+
+csApp::csApp()
+{
+ m_docManager = NULL;
+ m_diagramPalette = NULL;
+ m_diagramToolBar = NULL;
+ m_projectTreeCtrl = NULL;
+ m_diagramPaletteSashWindow = NULL;
+ m_projectSashWindow = NULL;
+ m_symbolDatabase = NULL;
+ m_pointSizeComboBox = NULL;
+ m_zoomComboBox = NULL;
+ m_shapeEditMenu = NULL;
+
+ // Configuration
+ m_mainFramePos.x = 20;
+ m_mainFramePos.y = 20;
+ m_mainFrameSize.x = 500;
+ m_mainFrameSize.y = 400;
+ m_gridStyle = csGRID_STYLE_INVISIBLE;
+ m_gridSpacing = 5;
+}
+
+csApp::~csApp()
+{
+}
+
+// Initialise this in OnInit, not statically
+bool csApp::OnInit(void)
+{
+ if (!wxResourceParseFile("studio_resources.wxr"))
+ {
+ wxMessageBox("Could not find or parse resource file: studio_resources.wxr", "Studio");
+ return FALSE;
+ }
+
+ m_helpController.Initialize("studio.hlp");
+
+ ReadOptions();
+
+ wxOGLInitialize();
+
+ InitSymbols();
+
+ //// Create a document manager
+ m_docManager = new wxDocManager;
+
+ //// Create a template relating drawing documents to their views
+ (void) new wxDocTemplate(m_docManager, "Diagram", "*.dia", "", "dia", "Diagram Doc", "Diagram View",
+ CLASSINFO(csDiagramDocument), CLASSINFO(csDiagramView));
+
+ // Create the main frame window
+
+ csFrame* frame = new csFrame(m_docManager, NULL, -1, "OGL Studio", m_mainFramePos, m_mainFrameSize,
+ wxDEFAULT_FRAME_STYLE | wxHSCROLL | wxVSCROLL);
+
+ // Give it an icon
+ frame->SetIcon(wxICON(studio));
+
+ // Make a menubar
+ wxMenu *fileMenu = new wxMenu;
+
+ fileMenu->Append(wxID_NEW, "&New...\tCtrl+N");
+ fileMenu->Append(wxID_OPEN, "&Open...\tCtrl+O");
+
+ fileMenu->AppendSeparator();
+
+ fileMenu->Append(wxID_PRINT, "&Print...\tCtrl+P");
+ fileMenu->Append(wxID_PRINT_SETUP, "Print &Setup...");
+ fileMenu->Append(wxID_PREVIEW, "Print Pre&view");
+ fileMenu->AppendSeparator();
+ fileMenu->Append(wxID_EXIT, "E&xit");
+
+ // A history of files visited. Use this menu.
+ m_docManager->FileHistoryUseMenu(fileMenu);
+
+ wxMenu *viewMenu = new wxMenu;
+ viewMenu->Append(ID_CS_SETTINGS, "&Settings...");
+
+ wxMenu *helpMenu = new wxMenu;
+ helpMenu->Append(wxID_HELP, "&Help Contents\tF1");
+ helpMenu->Append(ID_CS_ABOUT, "&About");
+
+ wxMenuBar *menuBar = new wxMenuBar;
+
+ menuBar->Append(fileMenu, "&File");
+ menuBar->Append(viewMenu, "&View");
+ menuBar->Append(helpMenu, "&Help");
+
+ // Associate the menu bar with the frame
+ frame->SetMenuBar(menuBar);
+
+ // Load the file history
+ wxConfig config("OGL Studio", "wxWindows");
+ m_docManager->FileHistoryLoad(config);
+
+ frame->CreateStatusBar();
+
+ // The ordering of these is important for layout purposes
+ CreateDiagramToolBar(frame);
+ CreatePalette(frame);
+ CreateProjectWindow(frame);
+
+ FillProjectTreeCtrl();
+
+ // Create the shape editing menu
+ m_shapeEditMenu = new wxMenu("", (wxFunction)studioShapeEditProc);
+ m_shapeEditMenu->Append(ID_CS_EDIT_PROPERTIES, "Edit properties");
+ m_shapeEditMenu->AppendSeparator();
+ m_shapeEditMenu->Append(ID_CS_ROTATE_CLOCKWISE, "Rotate clockwise");
+ m_shapeEditMenu->Append(ID_CS_ROTATE_ANTICLOCKWISE, "Rotate anticlockwise");
+ m_shapeEditMenu->AppendSeparator();
+ m_shapeEditMenu->Append(ID_CS_CUT, "Cut");
+
+ frame->Show(TRUE);
+
+ SetTopWindow(frame);
+
+ return TRUE;
+}
+
+int csApp::OnExit(void)
+{
+ WriteOptions();
+
+ delete m_symbolDatabase;
+ m_symbolDatabase = NULL;
+
+ delete m_docManager;
+ m_docManager = NULL;
+
+ delete m_shapeEditMenu;
+ m_shapeEditMenu = NULL;
+
+ wxOGLCleanUp();
+
+ return 0;
+}
+
+/*
+ * Centralised code for creating a document frame.
+ * Called from view.cpp, when a view is created.
+ */
+
+wxMDIChildFrame *csApp::CreateChildFrame(wxDocument *doc, wxView *view, wxMenu** editMenuRet)
+{
+ //// Make a child frame
+ csMDIChildFrame *subframe = new csMDIChildFrame(doc, view, ((wxDocMDIParentFrame*)GetTopWindow()), -1, "Child Frame",
+ wxPoint(10, 10), wxSize(300, 300), wxDEFAULT_FRAME_STYLE);
+
+#ifdef __WXMSW__
+ subframe->SetIcon(wxString("chart"));
+#endif
+#ifdef __X__
+ subframe->SetIcon(wxIcon("doc.xbm"));
+#endif
+
+ //// Make a menubar
+ wxMenu *fileMenu = new wxMenu;
+
+ fileMenu->Append(wxID_NEW, "&New...\tCtrl+N");
+ fileMenu->Append(wxID_OPEN, "&Open...\tCtrl+O");
+ fileMenu->Append(wxID_CLOSE, "&Close\tCtrl+W");
+ fileMenu->Append(wxID_SAVE, "&Save\tCtrl+S");
+ fileMenu->Append(wxID_SAVEAS, "Save &As...\tF12");
+
+ fileMenu->AppendSeparator();
+ fileMenu->Append(wxID_PRINT, "&Print...\tCtrl+P");
+ fileMenu->Append(wxID_PRINT_SETUP, "Print &Setup...");
+ fileMenu->Append(wxID_PREVIEW, "Print Pre&view");
+
+ fileMenu->AppendSeparator();
+ fileMenu->Append(wxID_EXIT, "E&xit");
+
+ wxMenu *editMenu = NULL;
+
+ editMenu = new wxMenu;
+ editMenu->Append(wxID_UNDO, "&Undo\tCtrl+Z");
+ editMenu->Append(wxID_REDO, "&Redo\tCtrl+Y");
+ editMenu->AppendSeparator();
+ editMenu->Append(wxID_CUT, "Cu&t\tCtrl+X");
+ editMenu->Append(wxID_COPY, "&Copy\tCtrl+C");
+ editMenu->Append(wxID_PASTE, "&Paste\tCtrl+V");
+ editMenu->Append(wxID_DUPLICATE, "&Duplicate\tCtrl+D");
+ editMenu->AppendSeparator();
+ editMenu->Append(wxID_CLEAR, "Cle&ar\tDelete");
+ editMenu->Append(ID_CS_SELECT_ALL, "Select A&ll\tCtrl+A");
+ editMenu->AppendSeparator();
+ editMenu->Append(ID_CS_EDIT_PROPERTIES, "Edit P&roperties...");
+
+ *editMenuRet = editMenu;
+
+ m_docManager->FileHistoryUseMenu(fileMenu);
+ m_docManager->FileHistoryAddFilesToMenu(fileMenu);
+
+ doc->GetCommandProcessor()->SetEditMenu(editMenu);
+
+ wxMenu *viewMenu = new wxMenu;
+ viewMenu->Append(ID_CS_SETTINGS, "&Settings...");
+
+ wxMenu *helpMenu = new wxMenu;
+ helpMenu->Append(wxID_HELP, "&Help Contents\tF1");
+ helpMenu->Append(ID_CS_ABOUT, "&About");
+
+ wxMenuBar *menuBar = new wxMenuBar;
+
+ menuBar->Append(fileMenu, "&File");
+ menuBar->Append(editMenu, "&Edit");
+ menuBar->Append(viewMenu, "&View");
+ menuBar->Append(helpMenu, "&Help");
+
+ //// Associate the menu bar with the frame
+ subframe->SetMenuBar(menuBar);
+
+ return subframe;
+}
+
+// Creates a canvas. Called by OnInit as a child of the main window
+csCanvas *csApp::CreateCanvas(wxView *view, wxFrame *parent)
+{
+ int width, height;
+ parent->GetClientSize(&width, &height);
+
+ // Non-retained canvas
+ csCanvas *canvas = new csCanvas((csDiagramView*) view, parent, 1000, wxPoint(0, 0), wxSize(width, height), 0);
+
+ wxColour bgColour("WHITE");
+ canvas->SetBackgroundColour(bgColour);
+
+ wxCursor cursor(wxCURSOR_HAND);
+ canvas->SetCursor(cursor);
+
+ // Give it scrollbars
+ canvas->SetScrollbars(20, 20, 100, 100);
+
+ return canvas;
+}
+
+void csApp::InitToolBar(wxToolBar* toolBar)
+{
+ wxBitmap* bitmaps[10];
+
+#ifdef __WXMSW__
+ bitmaps[0] = new wxBitmap("new", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[1] = new wxBitmap("open", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[2] = new wxBitmap("save", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[3] = new wxBitmap("copy", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[4] = new wxBitmap("cut", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[5] = new wxBitmap("paste", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[6] = new wxBitmap("print", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[7] = new wxBitmap("help", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[8] = new wxBitmap("undo", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[9] = new wxBitmap("redo", wxBITMAP_TYPE_RESOURCE);
+#elif defined(__WXGTK__) || defined(__WXMOTIF__)
+ bitmaps[0] = new wxBitmap( new_xpm );
+ bitmaps[1] = new wxBitmap( open_xpm );
+ bitmaps[2] = new wxBitmap( save_xpm );
+ bitmaps[3] = new wxBitmap( copy_xpm );
+ bitmaps[4] = new wxBitmap( cut_xpm );
+ bitmaps[5] = new wxBitmap( paste_xpm );
+ bitmaps[6] = new wxBitmap( print_xpm );
+ bitmaps[7] = new wxBitmap( help_xpm );
+ bitmaps[8] = new wxBitmap( undo_xpm );
+ bitmaps[9] = new wxBitmap( redo_xpm );
+#else
+#error "Not implemented for this platform."
+#endif
+
+ toolBar->AddTool(wxID_NEW, *bitmaps[0], wxNullBitmap, FALSE, -1, -1, NULL, "New file");
+ toolBar->AddTool(wxID_OPEN, *bitmaps[1], wxNullBitmap, FALSE, -1, -1, NULL, "Open file");
+ toolBar->AddTool(wxID_SAVE, *bitmaps[2], wxNullBitmap, FALSE, -1, -1, NULL, "Save file");
+ toolBar->AddSeparator();
+ toolBar->AddTool(wxID_PRINT, *bitmaps[6], wxNullBitmap, FALSE, -1, -1, NULL, "Print");
+ toolBar->AddSeparator();
+ toolBar->AddTool(wxID_COPY, *bitmaps[3], wxNullBitmap, FALSE, -1, -1, NULL, "Copy");
+ toolBar->AddTool(wxID_CUT, *bitmaps[4], wxNullBitmap, FALSE, -1, -1, NULL, "Cut");
+ toolBar->AddTool(wxID_PASTE, *bitmaps[5], wxNullBitmap, FALSE, -1, -1, NULL, "Paste");
+ toolBar->AddSeparator();
+ toolBar->AddTool(wxID_UNDO, *bitmaps[8], wxNullBitmap, FALSE, -1, -1, NULL, "Undo");
+ toolBar->AddTool(wxID_REDO, *bitmaps[9], wxNullBitmap, FALSE, -1, -1, NULL, "Redo");
+ toolBar->AddSeparator();
+ toolBar->AddTool(wxID_HELP, *bitmaps[7], wxNullBitmap, FALSE, -1, -1, NULL, "Help");
+
+ toolBar->Realize();
+
+ toolBar->EnableTool(wxID_COPY, FALSE);
+ toolBar->EnableTool(wxID_PASTE, FALSE);
+ toolBar->EnableTool(wxID_PRINT, FALSE);
+ toolBar->EnableTool(wxID_UNDO, FALSE);
+ toolBar->EnableTool(wxID_REDO, FALSE);
+
+ int i;
+ for (i = 0; i < 10; i++)
+ delete bitmaps[i];
+}
+
+// Create and initialise the diagram toolbar
+void csApp::CreateDiagramToolBar(wxFrame* parent)
+{
+ // First create a layout window
+ wxSashLayoutWindow* win = new wxSashLayoutWindow(parent, ID_LAYOUT_WINDOW_DIAGRAM_TOOLBAR, wxDefaultPosition, wxSize(200, 30), wxNO_BORDER|wxSW_3D|wxCLIP_CHILDREN);
+ win->SetDefaultSize(wxSize(10000, 30));
+ win->SetOrientation(wxLAYOUT_HORIZONTAL);
+ win->SetAlignment(wxLAYOUT_TOP);
+ win->SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
+
+ m_diagramToolBarSashWindow = win;
+ m_diagramToolBarSashWindow->Show(FALSE);
+
+ // Create the actual toolbar
+ m_diagramToolBar = new wxToolBar(win, -1, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL|wxNO_BORDER|wxTB_FLAT);
+
+ wxBitmap* bitmaps[11];
+
+#ifdef __WXMSW__
+ bitmaps[0] = new wxBitmap("alignl", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[1] = new wxBitmap("alignr", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[2] = new wxBitmap("alignt", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[3] = new wxBitmap("alignb", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[4] = new wxBitmap("horiz", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[5] = new wxBitmap("vert", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[6] = new wxBitmap("copysize", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[7] = new wxBitmap("linearrow", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[8] = new wxBitmap("newpoint", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[9] = new wxBitmap("cutpoint", wxBITMAP_TYPE_RESOURCE);
+ bitmaps[10] = new wxBitmap("straighten", wxBITMAP_TYPE_RESOURCE);
+#elif defined(__WXGTK__) || defined(__WXMOTIF__)
+ bitmaps[0] = new wxBitmap( alignl_xpm );
+ bitmaps[1] = new wxBitmap( alignr_xpm );
+ bitmaps[2] = new wxBitmap( alignt_xpm );
+ bitmaps[3] = new wxBitmap( alignb_xpm );
+ bitmaps[4] = new wxBitmap( horiz_xpm );
+ bitmaps[5] = new wxBitmap( vert_xpm );
+ bitmaps[6] = new wxBitmap( copysize_xpm );
+ bitmaps[7] = new wxBitmap( linearrow_xpm );
+ bitmaps[8] = new wxBitmap( newpoint_xpm );
+ bitmaps[9] = new wxBitmap( cutpoint_xpm );
+ bitmaps[10] = new wxBitmap( straight_xpm );
+#else
+#error "Not implemented for this platform."
+#endif
+
+ m_diagramToolBar->AddTool(DIAGRAM_TOOLBAR_ALIGNL, *bitmaps[0], wxNullBitmap, FALSE, -1, -1, NULL, "Align left");
+ m_diagramToolBar->AddTool(DIAGRAM_TOOLBAR_ALIGNR, *bitmaps[1], wxNullBitmap, FALSE, -1, -1, NULL, "Align right");
+ m_diagramToolBar->AddTool(DIAGRAM_TOOLBAR_ALIGNT, *bitmaps[2], wxNullBitmap, FALSE, -1, -1, NULL, "Align top");
+ m_diagramToolBar->AddTool(DIAGRAM_TOOLBAR_ALIGNB, *bitmaps[3], wxNullBitmap, FALSE, -1, -1, NULL, "Align bottom");
+ m_diagramToolBar->AddTool(DIAGRAM_TOOLBAR_ALIGN_HORIZ, *bitmaps[4], wxNullBitmap, FALSE, -1, -1, NULL, "Align horizontally");
+ m_diagramToolBar->AddTool(DIAGRAM_TOOLBAR_ALIGN_VERT, *bitmaps[5], wxNullBitmap, FALSE, -1, -1, NULL, "Align vertically");
+ m_diagramToolBar->AddTool(DIAGRAM_TOOLBAR_COPY_SIZE, *bitmaps[6], wxNullBitmap, FALSE, -1, -1, NULL, "Copy size");
+ m_diagramToolBar->AddSeparator();
+ m_diagramToolBar->AddTool(DIAGRAM_TOOLBAR_LINE_ARROW, *bitmaps[7], wxNullBitmap, TRUE, -1, -1, NULL, "Toggle arrow");
+ m_diagramToolBar->AddTool(DIAGRAM_TOOLBAR_NEW_POINT, *bitmaps[8], wxNullBitmap, FALSE, -1, -1, NULL, "New line point");
+ m_diagramToolBar->AddTool(DIAGRAM_TOOLBAR_CUT_POINT, *bitmaps[9], wxNullBitmap, FALSE, -1, -1, NULL, "Cut line point");
+ m_diagramToolBar->AddTool(DIAGRAM_TOOLBAR_STRAIGHTEN, *bitmaps[10], wxNullBitmap, FALSE, -1, -1, NULL, "Straighten lines");
+
+ m_diagramToolBar->Realize();
+
+ int i;
+ for (i = 0; i < 11; i++)
+ delete bitmaps[i];
+
+ // Create a combobox for point size
+ int maxPointSize = 40;
+ wxString *pointSizes = new wxString[maxPointSize];
+ for (i = 1; i <= maxPointSize; i++)
+ {
+ pointSizes[i-1].Printf("%d", i);
+ }
+
+ int controlX = 260;
+ int pointSizeW = 40;
+ int pointSizeH = 18;
+ int zoomW = 60;
+ int zoomH = 18;
+#ifdef __WXMOTIF__
+ controlX += 70;
+ pointSizeW = 60;
+ pointSizeH = 22;
+ zoomW = 60;
+ zoomH = 22;
+#endif
+
+ m_pointSizeComboBox = new wxComboBox(m_diagramToolBar, ID_WINDOW_POINT_SIZE_COMBOBOX,
+ "", wxPoint(controlX, 1), wxSize(pointSizeW, pointSizeH), maxPointSize, pointSizes);
+ delete[] pointSizes;
+
+ m_pointSizeComboBox->SetSelection(10 - 1);
+
+ // Create a combobox for zooming
+ int maxZoom = 200;
+ int minZoom = 5;
+ int increment = 5;
+ int noStrings = (maxZoom - minZoom)/5 ;
+ wxString *zoomStrings = new wxString[noStrings];
+ for (i = 0; i < noStrings; i ++)
+ {
+ zoomStrings[noStrings - i - 1].Printf("%d%%", (i*increment + minZoom));
+ }
+
+ controlX += pointSizeW + 10;
+
+ m_zoomComboBox = new wxComboBox(m_diagramToolBar, ID_WINDOW_ZOOM_COMBOBOX,
+ "", wxPoint(controlX, 1), wxSize(zoomW, zoomH), noStrings, zoomStrings);
+ delete[] zoomStrings;
+
+ // i = (zoom - minZoom)/increment
+ // index = noStrings - i - 1
+ // 100%
+ i = (100 - minZoom)/increment;
+ m_zoomComboBox->SetSelection(noStrings - i - 1);
+}
+
+// Read/write configuration information
+bool csApp::ReadOptions()
+{
+ wxConfig config("OGL Studio", "wxWindows");
+
+ config.Read("mainX", & m_mainFramePos.x);
+ config.Read("mainY", & m_mainFramePos.y);
+ config.Read("mainWidth", & m_mainFrameSize.x);
+ config.Read("mainHeight", & m_mainFrameSize.y);
+ config.Read("gridStyle", & m_gridStyle);
+ config.Read("gridSpacing", & m_gridSpacing);
+
+ return TRUE;
+}
+
+bool csApp::WriteOptions()
+{
+ wxConfig config("OGL Studio", "wxWindows");
+
+ config.Write("mainX", m_mainFramePos.x);
+ config.Write("mainY", m_mainFramePos.y);
+ config.Write("mainWidth", m_mainFrameSize.x);
+ config.Write("mainHeight", m_mainFrameSize.y);
+ config.Write("gridStyle", m_gridStyle);
+ config.Write("gridSpacing", m_gridSpacing);
+
+ m_docManager->FileHistorySave(config);
+
+ return TRUE;
+}
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: Studio.h
+// Purpose: Studio application class
+// Author: Julian Smart
+// Modified by:
+// Created: 27/7/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _STUDIO_STUDIO_H_
+#define _STUDIO_STUDIO_H_
+
+#include <wx/docmdi.h>
+#include <wx/help.h>
+
+#include <ogl.h>
+#include <canvas.h>
+#include "shapes.h"
+
+class csEditorToolPalette;
+class csProjectTreeCtrl;
+class csCanvas;
+class csSymbolDatabase;
+class wxSashLayoutWindow;
+class csFrame;
+
+// Grid style
+#define csGRID_STYLE_NONE 0
+#define csGRID_STYLE_INVISIBLE 1
+#define csGRID_STYLE_DOTTED 2
+
+// Define a new application
+class csApp: public wxApp
+{
+ friend csFrame;
+public:
+ csApp();
+ ~csApp();
+
+// Operations
+ bool OnInit(void);
+ int OnExit(void);
+
+ // Read/write configuration information
+ bool ReadOptions();
+ bool WriteOptions();
+
+ // Create the diagram tool palette
+ bool CreatePalette(wxFrame *parent);
+
+ // Create the project window
+ bool CreateProjectWindow(wxFrame *parent);
+
+ // Initialise the general toolbar
+ void InitToolBar(wxToolBar* toolBar);
+
+ // Create and initialise the diagram toolbar
+ void CreateDiagramToolBar(wxFrame* parent);
+
+ wxMDIChildFrame *CreateChildFrame(wxDocument *doc, wxView *view, wxMenu** editMenu);
+ csCanvas *CreateCanvas(wxView *view, wxFrame *parent);
+
+ // Fill out the project tree control
+ void FillProjectTreeCtrl();
+
+ // Add symbols to database
+ void InitSymbols();
+
+// Accessors
+ csEditorToolPalette* GetDiagramPalette() const { return m_diagramPalette; }
+ wxToolBar* GetDiagramToolBar() const { return m_diagramToolBar; }
+ csProjectTreeCtrl* GetProjectTreeCtrl() const { return m_projectTreeCtrl; }
+ wxSashLayoutWindow* GetDiagramPaletteSashWindow() const { return m_diagramPaletteSashWindow; }
+ wxSashLayoutWindow* GetProjectSashWindow() const { return m_projectSashWindow; }
+ wxSashLayoutWindow* GetDiagramToolBarSashWindow() const { return m_diagramToolBarSashWindow; }
+ csSymbolDatabase* GetSymbolDatabase() const { return m_symbolDatabase; }
+ wxComboBox* GetPointSizeComboBox() const { return m_pointSizeComboBox; }
+ wxComboBox* GetZoomComboBox() const { return m_zoomComboBox; }
+ wxMenu* GetShapeEditMenu() const { return m_shapeEditMenu; }
+ wxDiagramClipboard& GetDiagramClipboard() const { return (wxDiagramClipboard&) m_diagramClipboard; }
+ wxDocManager* GetDocManager() const { return m_docManager; }
+ wxHelpController& GetHelpController() const { return (wxHelpController&) m_helpController; }
+
+ int GetGridStyle() const { return m_gridStyle; }
+ void SetGridStyle(int style) { m_gridStyle = style; }
+
+ int GetGridSpacing() const { return m_gridSpacing; }
+ void SetGridSpacing(int spacing) { m_gridSpacing = spacing; }
+
+protected:
+ wxDocManager* m_docManager;
+ wxSashLayoutWindow* m_diagramPaletteSashWindow;
+ wxSashLayoutWindow* m_diagramToolBarSashWindow;
+ wxSashLayoutWindow* m_projectSashWindow;
+ csEditorToolPalette* m_diagramPalette;
+ csProjectTreeCtrl* m_projectTreeCtrl;
+ csSymbolDatabase* m_symbolDatabase;
+ wxToolBar* m_diagramToolBar;
+ wxComboBox* m_pointSizeComboBox;
+ wxComboBox* m_zoomComboBox;
+ wxMenu* m_shapeEditMenu;
+
+ // Configuration
+ wxPoint m_mainFramePos;
+ wxSize m_mainFrameSize;
+ int m_gridStyle;
+ int m_gridSpacing;
+
+ // Diagram clipboard
+ csDiagramClipboard m_diagramClipboard;
+
+ // Help instance
+ wxHelpController m_helpController;
+};
+
+DECLARE_APP(csApp)
+
+#define ID_CS_CUT wxID_CUT
+#define ID_CS_ADD_SHAPE 2
+#define ID_CS_ADD_LINE 3
+// #define ID_CS_EDIT_LABEL 4
+#define ID_CS_EDIT_PROPERTIES 4
+#define ID_CS_CHANGE_BACKGROUND_COLOUR 5
+#define ID_CS_MOVE 6
+#define ID_CS_SIZE 7
+#define ID_CS_FONT_CHANGE 8
+#define ID_CS_ARROW_CHANGE 9
+#define ID_CS_ROTATE_CLOCKWISE 11
+#define ID_CS_ROTATE_ANTICLOCKWISE 12
+#define ID_CS_CHANGE_LINE_ORDERING 13 // Change the list of lines for a wxShape
+#define ID_CS_CHANGE_LINE_ATTACHMENT 14 // Change the attachment point for one end of a line
+#define ID_CS_ALIGN 15
+#define ID_CS_NEW_POINT 16
+#define ID_CS_CUT_POINT 17
+#define ID_CS_STRAIGHTEN 18
+#define ID_CS_MOVE_LINE_POINT 19
+#define ID_CS_MOVE_LABEL 20
+#define ID_CS_ADD_SHAPE_SELECT 21
+#define ID_CS_ADD_LINE_SELECT 22
+
+#define ID_CS_ABOUT 100
+#define ID_CS_SELECT_ALL 102
+#define ID_CS_SETTINGS 103
+
+#define ID_LAYOUT_WINDOW_PALETTE 200
+#define ID_LAYOUT_WINDOW_DIAGRAM_TOOLBAR 201
+#define ID_LAYOUT_WINDOW_PROJECT 202
+
+#define ID_DIAGRAM_PALETTE 250
+
+#define ID_WINDOW_PROJECT_TREE 300
+#define ID_WINDOW_POINT_SIZE_COMBOBOX 301
+#define ID_WINDOW_ZOOM_COMBOBOX 302
+
+#define DIAGRAM_TOOLBAR_ALIGNL 500
+#define DIAGRAM_TOOLBAR_ALIGNR 501
+#define DIAGRAM_TOOLBAR_ALIGNB 502
+#define DIAGRAM_TOOLBAR_ALIGNT 503
+#define DIAGRAM_TOOLBAR_ALIGN_HORIZ 504
+#define DIAGRAM_TOOLBAR_ALIGN_VERT 505
+#define DIAGRAM_TOOLBAR_COPY_SIZE 506
+#define DIAGRAM_TOOLBAR_LINE_ARROW 507
+#define DIAGRAM_TOOLBAR_NEW_POINT 508
+#define DIAGRAM_TOOLBAR_CUT_POINT 509
+#define DIAGRAM_TOOLBAR_STRAIGHTEN 510
+
+#endif
+ // _STUDIO_STUDIO_H_
+
--- /dev/null
+aaaa ICON "studio.ico"
+
+/* Useful if PROVIDE_DEFAULT_ICONS is set in wx_setup.h */
+#define IHaveMDIParentIcon
+#define IHaveMDIChildIcon
+
+wxSTD_MDIPARENTFRAME ICON "studio.ico"
+wxSTD_MDICHILDFRAME ICON "studio.ico"
+
+studio ICON "studio.ico"
+folder1 ICON "bitmaps/folder1.ico"
+file1 ICON "bitmaps/file1.ico"
+
+new BITMAP "bitmaps/new.bmp"
+open BITMAP "bitmaps/open.bmp"
+save BITMAP "bitmaps/save.bmp"
+copy BITMAP "bitmaps/copy.bmp"
+cut BITMAP "bitmaps/cut.bmp"
+paste BITMAP "bitmaps/paste.bmp"
+print BITMAP "bitmaps/print.bmp"
+help BITMAP "bitmaps/help.bmp"
+undo BITMAP "bitmaps/undo.bmp"
+redo BITMAP "bitmaps/redo.bmp"
+
+arrowtool BITMAP "bitmaps/arrow.bmp"
+texttool BITMAP "bitmaps/texttool.bmp"
+
+alignl BITMAP "bitmaps/alignl.bmp"
+alignb BITMAP "bitmaps/alignb.bmp"
+alignr BITMAP "bitmaps/alignr.bmp"
+alignt BITMAP "bitmaps/alignt.bmp"
+copysize BITMAP "bitmaps/copysize.bmp"
+vert BITMAP "bitmaps/vert.bmp"
+horiz BITMAP "bitmaps/horiz.bmp"
+linearrow BITMAP "bitmaps/linearrow.bmp"
+newpoint BITMAP "bitmaps/newpoint.bmp"
+cutpoint BITMAP "bitmaps/cutpoint.bmp"
+straighten BITMAP "bitmaps/straight.bmp"
+
+#include "wx/msw/wx.rc"
+
--- /dev/null
+/* XPM */
+static char *clipstudio_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 6 1",
+" c Black",
+". c Blue",
+"X c #00bf00",
+"o c Red",
+"O c Yellow",
+"+ c Gray100",
+/* pixels */
+" ",
+" oooooo +++++++++++++++++++++++ ",
+" oooooo +++++++++++++++++++++++ ",
+" oooooo +++++++++++++++++++++++ ",
+" oooooo +++++++++++++++++++++++ ",
+" oooooo +++++++++++++++++++++++ ",
+" oooooo +++++++++++++++++++++++ ",
+" oooooo +++++++++++++++++++++++ ",
+" ",
+" ++++++ ++++++++++++++++++ .... ",
+" ++++++ ++++++++++++++++++ .... ",
+" ++++++ ++++++++++++++++++ .... ",
+" ++++++ ++++++++++++++++++ .... ",
+" ++++++ ++++++++++++++++++ .... ",
+" ++++++ ++++++++++++++++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++ ",
+" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
+" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
+" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
+" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
+" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
+" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
+" "
+};
--- /dev/null
+/*
+ * studio_resources.h
+ * Window identifiers file written by Dialog Editor
+ */
+
+#define ID_GRID_STYLE 6004
+#define ID_TEXTCTRL5115 5115
+#define ID_TEXTCTRL5107 5107
+#define ID_LABEL_DIALOG 6008
+#define ID_GRID_SPACING 6007
+#define IDD_LABEL_ENTRY 100
+#define ID_STATIC 300
+#define ID_DIALOG100 100
+#define ID_DIALOG6001 6001
+#define ID_STATIC6005 6005
+#define ID_STATIC6006 6006
+#define ID_STATIC5116 5116
+#define ID_STATIC6009 6009
+#define ID_LABELTEXT 101
+#define ID_CONTROL101 106
+#define ID_CONTROL102 107
+#define ID_CONTROL111 111
+#define ID_CONTROL120 120
+#define ID_CONTROL103 108
+#define ID_CONTROL121 5105
+#define ID_CONTROL130 5114
+#define ID_CONTROL104 109
+#define ID_CONTROL122 5106
+#define ID_CONTROL131 121
+#define ID_CONTROL105 110
+#define ID_CONTROL114 115
+#define ID_CONTROL123 5107
+#define ID_CONTROL132 122
+#define ID_CONTROL124 5108
+#define ID_CONTROL116 116
+#define ID_CONTROL125 5109
+#define ID_CONTROL117 117
+#define ID_CONTROL126 5110
+#define ID_CONTROL118 118
+#define ID_CONTROL127 5111
+#define ID_CONTROL119 119
+#define ID_CONTROL128 5112
+#define ID_CONTROL129 5113
+#define ID_GENERAL_SETTINGS_DIALOG 2000
--- /dev/null
+static char *semi_circle = "dialog(name = 'semi_circle',\
+ style = 'wxNO_BORDER',\
+ title = 'SemiCircle',\
+ id = 100,\
+ x = 10, y = 40, width = 365, height = 405,\
+ background_colour = 'C0C0C0',\
+ use_dialog_units = 0,\
+ use_system_defaults = 0,\
+ font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif'],\
+ control = [106, wxStaticText, 'Segment Id', '0', 'statictext7', 14, 163, 64, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [107, wxTextCtrl, '', '0', 'textctrl8', 108, 162, 120, 19, ''],\
+ control = [108, wxStaticText, 'Num Channels', '0', 'statictext9', 14, 208, 79, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [109, wxTextCtrl, '1', '0', 'textctrl10', 108, 206, 30, 19, '1'],\
+ control = [110, wxStaticText, 'Attributes', '0', 'statictext11', 14, 245, 54, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [111, wxTextCtrl, '', '0', 'textctrl12', 108, 245, 120, 19, ''],\
+ control = [5106, wxRadioBox, 'Scope', 'wxRA_SPECIFY_COLS', 'radiobox1', 12, 13, 236, 44, ['Process', 'Application', 'Project'], 3],\
+ control = [5108, wxRadioBox, 'Resource', 'wxRA_SPECIFY_ROWS', 'radiobox3', 174, 68, 72, 82, ['Heap', 'Segment', 'Any'], 3],\
+ control = [5109, wxRadioBox, 'Volatility', 'wxRA_SPECIFY_ROWS', 'radiobox4', 12, 69, 81, 63, ['Permanent', 'Temporary'], 2],\
+ control = [5111, wxStaticText, 'Num Events', '0', 'statictext1', 154, 208, 68, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [5112, wxTextCtrl, '1', '0', 'textctrl2', 230, 205, 40, 19, '1']).";
+
+static char *general_shape_properties_dialog = "panel(name = 'general_shape_properties_dialog',\
+ style = 'wxNO_BORDER',\
+ title = 'General',\
+ id = 100,\
+ x = 10, y = 40, width = 400, height = 400,\
+ background_colour = 'C0C0C0',\
+ use_dialog_units = 0,\
+ use_system_defaults = 0,\
+ font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif'],\
+ control = [101, wxTextCtrl, '', '0', 'textctrl3', 8, 31, 203, 24, ''],\
+ control = [300, wxStaticText, 'Name:', '0', 'message4', 8, 11, 41, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [5115, wxTextCtrl, '', 'wxTE_MULTILINE', 'textctrl1', 8, 101, 204, 100, ''],\
+ control = [5116, wxStaticText, 'Description:', '0', 'statictext2', 9, 79, 66, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']]).";
+
+static char *diagram_settings_dialog = "dialog(name = 'diagram_settings_dialog',\
+ style = 'wxNO_BORDER',\
+ title = 'Diagram settings',\
+ id = 6001,\
+ x = 10, y = 40, width = 400, height = 300,\
+ background_colour = 'C0C0C0',\
+ use_dialog_units = 0,\
+ use_system_defaults = 0,\
+ font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif'],\
+ control = [6004, wxChoice, '', '0', 'choice4', 13, 31, 85, 21, ['None', 'Invisible', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted', 'Dotted']],\
+ control = [6005, wxStaticText, 'Grid style:', '0', 'statictext5', 13, 11, 56, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [6006, wxStaticText, 'Grid spacing:', '0', 'statictext6', 137, 11, 72, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [6007, wxTextCtrl, '', '0', 'textctrl7', 136, 31, 66, 21, '']).";
+
+static char *general_settings_dialog = "dialog(name = 'general_settings_dialog',\
+ style = 'wxNO_BORDER | wxCAPTION | wxSYSTEM_MENU',\
+ title = '',\
+ id = 2000,\
+ x = 10, y = 40, width = 375, height = 325,\
+ background_colour = 'C0C0C0',\
+ use_dialog_units = 0,\
+ use_system_defaults = 0,\
+ font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif'],\
+ control = [300, wxStaticText, 'Project path:', '0', 'statictext3', 12, 15, 70, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [5107, wxTextCtrl, '', '0', 'textctrl4', 12, 34, 183, 24, '']).";
+
+static char *wide_rectangle = "dialog(name = 'wide_rectangle',\
+ style = 'wxNO_BORDER',\
+ title = 'Wide Rectangle',\
+ id = 100,\
+ x = 10, y = 40, width = 355, height = 405,\
+ background_colour = 'C0C0C0',\
+ use_dialog_units = 0,\
+ use_system_defaults = 0,\
+ font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif'],\
+ control = [106, wxStaticText, 'Segment Id', '0', 'statictext7', 13, 184, 64, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [107, wxTextCtrl, '', '0', 'textctrl8', 13, 184, 120, 19, ''],\
+ control = [108, wxStaticText, 'Num Channels', '0', 'statictext9', 13, 184, 79, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [109, wxTextCtrl, '', '0', 'textctrl10', 13, 184, 30, 19, ''],\
+ control = [110, wxStaticText, 'Attributes', '0', 'statictext11', 13, 184, 54, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [111, wxTextCtrl, '', '0', 'textctrl12', 13, 184, 120, 19, ''],\
+ control = [5106, wxRadioBox, 'Scope', 'wxRA_SPECIFY_COLS', 'radiobox1', 13, 11, 313, 46, ['Process', 'Application', 'Project'], 3],\
+ control = [5108, wxRadioBox, 'Resource', 'wxRA_SPECIFY_ROWS', 'radiobox3', 166, 70, 72, 82, ['Heap', 'Segment', 'Any'], 3],\
+ control = [5109, wxRadioBox, 'Volatility', 'wxRA_SPECIFY_ROWS', 'radiobox4', 14, 73, 81, 63, ['Permanent', 'Temporary'], 2]).";
+
+static char *thin_rectangle = "dialog(name = 'thin_rectangle',\
+ style = 'wxNO_BORDER',\
+ title = 'Thin Rectangle',\
+ id = 100,\
+ x = 10, y = 40, width = 361, height = 405,\
+ background_colour = 'C0C0C0',\
+ use_dialog_units = 0,\
+ use_system_defaults = 0,\
+ font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif'],\
+ control = [106, wxStaticText, 'Segment Id', '0', 'statictext7', 12, 169, 64, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [107, wxTextCtrl, '', '0', 'textctrl8', 106, 168, 120, 19, ''],\
+ control = [108, wxStaticText, 'Num Channels', '0', 'statictext9', 12, 204, 79, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [109, wxTextCtrl, '1', '0', 'textctrl10', 106, 202, 30, 19, '1'],\
+ control = [110, wxStaticText, 'Attributes', '0', 'statictext11', 12, 267, 54, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [111, wxTextCtrl, '', '0', 'textctrl12', 106, 265, 120, 19, ''],\
+ control = [5106, wxRadioBox, 'Scope', 'wxRA_SPECIFY_COLS', 'radiobox1', 13, 16, 236, 44, ['Process', 'Application', 'Project'], 3],\
+ control = [5108, wxRadioBox, 'Resource', 'wxRA_SPECIFY_ROWS', 'radiobox3', 176, 73, 72, 82, ['Heap', 'Segment', 'Any'], 3],\
+ control = [5109, wxRadioBox, 'Volatility', 'wxRA_SPECIFY_ROWS', 'radiobox4', 14, 73, 81, 63, ['Permanent', 'Temporary'], 2],\
+ control = [5111, wxStaticText, 'Num Events', '0', 'statictext1', 156, 205, 68, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [5112, wxTextCtrl, '1', '0', 'textctrl2', 228, 202, 40, 19, '1'],\
+ control = [5113, wxStaticText, 'Num Fields', '0', 'statictext3', 12, 234, 62, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [5114, wxTextCtrl, '1', '0', 'textctrl4', 106, 234, 40, 19, '1']).";
+
+static char *circle = "dialog(name = 'circle',\
+ style = 'wxNO_BORDER',\
+ title = 'Circle',\
+ id = 100,\
+ x = 10, y = 40, width = 361, height = 405,\
+ background_colour = 'C0C0C0',\
+ use_dialog_units = 0,\
+ use_system_defaults = 0,\
+ font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif'],\
+ control = [106, wxStaticText, 'Segment Id', '0', 'statictext7', 12, 169, 64, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [107, wxTextCtrl, '', '0', 'textctrl8', 106, 168, 120, 19, ''],\
+ control = [108, wxStaticText, 'Num Channels', '0', 'statictext9', 12, 204, 79, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [109, wxTextCtrl, '1', '0', 'textctrl10', 106, 202, 30, 19, '1'],\
+ control = [110, wxStaticText, 'Attributes', '0', 'statictext11', 12, 267, 54, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [111, wxTextCtrl, '', '0', 'textctrl12', 106, 265, 120, 19, ''],\
+ control = [5106, wxRadioBox, 'Scope', 'wxRA_SPECIFY_COLS', 'radiobox1', 13, 16, 236, 44, ['Process', 'Application', 'Project'], 3],\
+ control = [5108, wxRadioBox, 'Resource', 'wxRA_SPECIFY_ROWS', 'radiobox3', 176, 73, 72, 82, ['Heap', 'Segment', 'Any'], 3],\
+ control = [5109, wxRadioBox, 'Volatility', 'wxRA_SPECIFY_ROWS', 'radiobox4', 14, 73, 81, 63, ['Permanent', 'Temporary'], 2],\
+ control = [5111, wxStaticText, 'Num Events', '0', 'statictext1', 156, 205, 68, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [5112, wxTextCtrl, '1', '0', 'textctrl2', 228, 202, 40, 19, '1'],\
+ control = [5113, wxStaticText, 'Num Fields', '0', 'statictext3', 12, 234, 62, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [5114, wxTextCtrl, '1', '0', 'textctrl4', 106, 234, 40, 19, '1']).";
+
+static char *triangle = "dialog(name = 'triangle',\
+ style = 'wxNO_BORDER',\
+ title = 'Triangle',\
+ id = 100,\
+ x = 10, y = 40, width = 362, height = 405,\
+ background_colour = 'C0C0C0',\
+ use_dialog_units = 0,\
+ use_system_defaults = 0,\
+ font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif'],\
+ control = [106, wxStaticText, 'Segment Id', '0', 'statictext7', 16, 170, 64, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [107, wxTextCtrl, '', '0', 'textctrl8', 110, 169, 120, 19, ''],\
+ control = [108, wxStaticText, 'Num Channels', '0', 'statictext9', 16, 213, 79, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [109, wxTextCtrl, '1', '0', 'textctrl10', 110, 213, 30, 19, '1'],\
+ control = [110, wxStaticText, 'Attributes', '0', 'statictext11', 16, 252, 54, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [111, wxTextCtrl, '', '0', 'textctrl12', 110, 252, 120, 19, ''],\
+ control = [5106, wxRadioBox, 'Scope', 'wxRA_SPECIFY_COLS', 'radiobox1', 14, 16, 236, 44, ['Process', 'Application', 'Project'], 3],\
+ control = [5108, wxRadioBox, 'Resource', 'wxRA_SPECIFY_ROWS', 'radiobox3', 178, 75, 72, 82, ['Heap', 'Segment', 'Any'], 3],\
+ control = [5109, wxRadioBox, 'Volatility', 'wxRA_SPECIFY_ROWS', 'radiobox4', 15, 75, 81, 63, ['Permanent', 'Temporary'], 2],\
+ control = [5111, wxStaticText, 'Num Events', '0', 'statictext1', 156, 215, 68, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [5112, wxTextCtrl, '1', '0', 'textctrl2', 227, 213, 40, 19, '1']).";
+
+static char *shape_label_dialog = "dialog(name = 'shape_label_dialog',\
+ style = 'wxRAISED_BORDER | wxCAPTION | wxTHICK_FRAME | wxSYSTEM_MENU',\
+ title = 'Edit Shape Label',\
+ id = 6008,\
+ x = 10, y = 10, width = 190, height = 60,\
+ background_colour = 'C0C0C0',\
+ use_dialog_units = 1,\
+ use_system_defaults = 0,\
+ font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif'],\
+ control = [6009, wxStaticText, 'Please enter a label for this shape.', '0', 'statictext2', 8, 6, 100, 6, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [101, wxTextCtrl, '', '0', 'textctrl4', 8, 18, 168, 11, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [5100, wxButton, 'OK', '0', 'button5', 100, 37, 36, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']],\
+ control = [5101, wxButton, 'Cancel', '0', 'button6', 140, 37, 36, 13, '',\
+ [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Sans Serif']]).";
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: symbols.cpp
+// Purpose: Implements the Studio symbol database
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+// #pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include <wx/wxprec.h>
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+#include <wx/wxexpr.h>
+
+#include "studio.h"
+#include "doc.h"
+#include "shapes.h"
+#include "view.h"
+#include "symbols.h"
+
+/*
+ * csSymbol
+ * Represents information about a symbol.
+ */
+
+csSymbol::csSymbol(const wxString& name, wxShape* shape)
+{
+ m_name = name;
+ m_shape = shape;
+ m_toolId = 0;
+}
+
+csSymbol::~csSymbol()
+{
+ delete m_shape;
+}
+
+/*
+ * A table of all possible shapes.
+ * We can use this to construct a palette, etc.
+ */
+csSymbolDatabase::csSymbolDatabase()
+{
+ m_currentId = 800;
+}
+
+csSymbolDatabase::~csSymbolDatabase()
+{
+ ClearSymbols();
+}
+
+void csSymbolDatabase::AddSymbol(csSymbol* symbol)
+{
+ symbol->SetToolId(m_currentId);
+ m_symbols.Append(symbol);
+
+ m_currentId ++;
+}
+
+void csSymbolDatabase::ClearSymbols()
+{
+ wxNode* node = m_symbols.First();
+ while (node)
+ {
+ csSymbol* symbol = (csSymbol*) node->Data();
+ delete symbol;
+
+ node = node->Next();
+ }
+ m_symbols.Clear();
+}
+
+csSymbol* csSymbolDatabase::FindSymbol(const wxString& name) const
+{
+ wxNode* node = m_symbols.First();
+ while (node)
+ {
+ csSymbol* symbol = (csSymbol*) node->Data();
+ if (symbol->GetName() == name)
+ return symbol;
+
+ node = node->Next();
+ }
+ return NULL;
+}
+
+csSymbol* csSymbolDatabase::FindSymbol(int toolId) const
+{
+ wxNode* node = m_symbols.First();
+ while (node)
+ {
+ csSymbol* symbol = (csSymbol*) node->Data();
+ if (symbol->GetToolId() == toolId)
+ return symbol;
+
+ node = node->Next();
+ }
+ return NULL;
+}
+
+// Add symbols to database
+void csApp::InitSymbols()
+{
+ m_symbolDatabase = new csSymbolDatabase;
+
+ wxShape* shape = new csCircleShape();
+ shape->AssignNewIds();
+ shape->SetEventHandler(new csEvtHandler(shape, shape, wxString("")));
+
+ m_symbolDatabase->AddSymbol(new csSymbol("Circle", shape));
+
+ shape = new csCircleShadowShape();
+ shape->AssignNewIds();
+ shape->SetEventHandler(new csEvtHandler(shape, shape, wxString("")));
+
+ m_symbolDatabase->AddSymbol(new csSymbol("Circle shadow", shape));
+
+ shape = new csThinRectangleShape();
+ shape->AssignNewIds();
+ shape->SetEventHandler(new csEvtHandler(shape, shape, wxString("")));
+
+ m_symbolDatabase->AddSymbol(new csSymbol("Thin Rectangle", shape));
+
+ shape = new csWideRectangleShape();
+ shape->AssignNewIds();
+ shape->SetEventHandler(new csEvtHandler(shape, shape, wxString("")));
+
+ m_symbolDatabase->AddSymbol(new csSymbol("Wide Rectangle", shape));
+
+ shape = new csSemiCircleShape();
+ shape->AssignNewIds();
+ shape->SetEventHandler(new csEvtHandler(shape, shape, wxString("")));
+
+ m_symbolDatabase->AddSymbol(new csSymbol("SemiCircle", shape));
+
+ shape = new csTriangleShape();
+ shape->AssignNewIds();
+ shape->SetEventHandler(new csEvtHandler(shape, shape, wxString("")));
+
+ m_symbolDatabase->AddSymbol(new csSymbol("Triangle", shape));
+
+ shape = new csOctagonShape();
+ shape->AssignNewIds();
+ shape->SetEventHandler(new csEvtHandler(shape, shape, wxString("")));
+
+ m_symbolDatabase->AddSymbol(new csSymbol("Octagon", shape));
+
+ shape = new csGroupShape();
+ shape->AssignNewIds();
+ shape->SetEventHandler(new csEvtHandler(shape, shape, wxString("")));
+
+ m_symbolDatabase->AddSymbol(new csSymbol("Group", shape));
+}
+
+wxBitmap* csSymbolDatabase::CreateToolBitmap(csSymbol* symbol)
+{
+ int objectBitmapSize = 32;
+
+ symbol->GetShape()->Recompute();
+
+ wxBitmap *newBitmap = new wxBitmap(objectBitmapSize, objectBitmapSize);
+
+ wxMemoryDC memDC;
+
+ double height, width, maxSize;
+ symbol->GetShape()->GetBoundingBoxMax(&width, &height);
+
+ if (height > width)
+ maxSize = height;
+ else
+ maxSize = width;
+
+ double borderMargin = 4.0;
+ double scaleFactor = (double)(objectBitmapSize / (maxSize + 2*borderMargin));
+ double centreX = (double)((objectBitmapSize/scaleFactor)/2.0)-1;
+ double centreY = centreX;
+
+ memDC.SetUserScale(scaleFactor, scaleFactor);
+
+ memDC.SelectObject(*newBitmap);
+ memDC.SetBackground(wxBrush(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE), wxSOLID));
+ memDC.Clear();
+ symbol->GetShape()->Show(TRUE);
+ symbol->GetShape()->Move(memDC, centreX, centreY);
+ memDC.SelectObject(wxNullBitmap);
+
+ return newBitmap;
+}
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: symbols.h
+// Purpose: Symbol classes (symbol database)
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _STUDIO_SYMBOLS_H_
+#define _STUDIO_SYMBOLS_H_
+
+#ifdef __GNUG__
+// #pragma interface
+#endif
+
+#include <wx/docview.h>
+#include <wx/string.h>
+#include <wx/wxexpr.h>
+
+#include "ogl.h"
+
+/*
+ * csSymbol
+ * Represents information about a symbol.
+ */
+
+class csSymbol: public wxObject
+{
+public:
+ csSymbol(const wxString& name, wxShape* shape);
+ ~csSymbol();
+
+ inline void SetName(const wxString& name) { m_name = name; }
+ inline wxString GetName() const { return m_name; }
+
+ inline void SetShape(wxShape* shape) { m_shape = shape; }
+ inline wxShape* GetShape() const { return m_shape; }
+
+ inline void SetToolId(int id) { m_toolId = id; }
+ inline int GetToolId() const { return m_toolId; }
+protected:
+ wxString m_name;
+ wxShape* m_shape;
+ int m_toolId;
+};
+
+/*
+ * A table of all possible shapes.
+ * We can use this to construct a palette, etc.
+ */
+class csSymbolDatabase: public wxObject
+{
+public:
+ csSymbolDatabase();
+ ~csSymbolDatabase();
+
+// Accessors
+ inline wxList& GetSymbols() const { return (wxList&) m_symbols; }
+
+// Operations
+ void AddSymbol(csSymbol* symbol);
+ void ClearSymbols();
+ csSymbol* FindSymbol(const wxString& name) const;
+ csSymbol* FindSymbol(int toolId) const;
+ wxBitmap* CreateToolBitmap(csSymbol* symbol);
+
+protected:
+ wxList m_symbols;
+ int m_currentId;
+};
+
+#endif
+ // _STUDIO_SYMBOLS_H_
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: view.cpp
+// Purpose: Implements view functionality
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+// #pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include <wx/wxprec.h>
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+#include <wx/colordlg.h>
+
+#if !wxUSE_DOC_VIEW_ARCHITECTURE
+#error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in wx_setup.h!
+#endif
+
+#include "studio.h"
+#include "doc.h"
+#include "view.h"
+#include "cspalette.h"
+#include "symbols.h"
+#include "dialogs.h"
+#include "basicp.h"
+#include "linesp.h"
+
+IMPLEMENT_DYNAMIC_CLASS(csDiagramView, wxView)
+
+BEGIN_EVENT_TABLE(csDiagramView, wxView)
+ EVT_MENU(wxID_CUT, csDiagramView::OnCut)
+ EVT_MENU(wxID_COPY, csDiagramView::OnCopy)
+ EVT_MENU(wxID_CLEAR, csDiagramView::OnClear)
+ EVT_MENU(wxID_PASTE, csDiagramView::OnPaste)
+ EVT_MENU(wxID_DUPLICATE, csDiagramView::OnDuplicate)
+ EVT_MENU(ID_CS_CHANGE_BACKGROUND_COLOUR, csDiagramView::OnChangeBackgroundColour)
+ EVT_MENU(ID_CS_EDIT_PROPERTIES, csDiagramView::OnEditProperties)
+ EVT_MENU(ID_CS_SELECT_ALL, csDiagramView::OnSelectAll)
+ EVT_TOOL(DIAGRAM_TOOLBAR_LINE_ARROW, csDiagramView::OnToggleArrowTool)
+ EVT_COMBOBOX(ID_WINDOW_POINT_SIZE_COMBOBOX, csDiagramView::OnPointSizeComboSel)
+ EVT_COMBOBOX(ID_WINDOW_ZOOM_COMBOBOX, csDiagramView::OnZoomSel)
+ EVT_TEXT(ID_WINDOW_POINT_SIZE_COMBOBOX, csDiagramView::OnPointSizeComboText)
+ EVT_TOOL(DIAGRAM_TOOLBAR_ALIGNL, csDiagramView::OnAlign)
+ EVT_TOOL(DIAGRAM_TOOLBAR_ALIGNR, csDiagramView::OnAlign)
+ EVT_TOOL(DIAGRAM_TOOLBAR_ALIGNB, csDiagramView::OnAlign)
+ EVT_TOOL(DIAGRAM_TOOLBAR_ALIGNT, csDiagramView::OnAlign)
+ EVT_TOOL(DIAGRAM_TOOLBAR_ALIGN_HORIZ, csDiagramView::OnAlign)
+ EVT_TOOL(DIAGRAM_TOOLBAR_ALIGN_VERT, csDiagramView::OnAlign)
+ EVT_TOOL(DIAGRAM_TOOLBAR_COPY_SIZE, csDiagramView::OnAlign)
+ EVT_TOOL(DIAGRAM_TOOLBAR_NEW_POINT, csDiagramView::OnNewLinePoint)
+ EVT_TOOL(DIAGRAM_TOOLBAR_CUT_POINT, csDiagramView::OnCutLinePoint)
+ EVT_TOOL(DIAGRAM_TOOLBAR_STRAIGHTEN, csDiagramView::OnStraightenLines)
+ EVT_UPDATE_UI(DIAGRAM_TOOLBAR_ALIGNL, csDiagramView::OnAlignUpdate)
+ EVT_UPDATE_UI(DIAGRAM_TOOLBAR_ALIGNR, csDiagramView::OnAlignUpdate)
+ EVT_UPDATE_UI(DIAGRAM_TOOLBAR_ALIGNB, csDiagramView::OnAlignUpdate)
+ EVT_UPDATE_UI(DIAGRAM_TOOLBAR_ALIGNT, csDiagramView::OnAlignUpdate)
+ EVT_UPDATE_UI(DIAGRAM_TOOLBAR_ALIGN_HORIZ, csDiagramView::OnAlignUpdate)
+ EVT_UPDATE_UI(DIAGRAM_TOOLBAR_ALIGN_VERT, csDiagramView::OnAlignUpdate)
+ EVT_UPDATE_UI(DIAGRAM_TOOLBAR_COPY_SIZE, csDiagramView::OnAlignUpdate)
+ EVT_UPDATE_UI(DIAGRAM_TOOLBAR_NEW_POINT, csDiagramView::OnNewLinePointUpdate)
+ EVT_UPDATE_UI(DIAGRAM_TOOLBAR_CUT_POINT, csDiagramView::OnCutLinePointUpdate)
+ EVT_UPDATE_UI(DIAGRAM_TOOLBAR_STRAIGHTEN, csDiagramView::OnStraightenLinesUpdate)
+ EVT_UPDATE_UI(DIAGRAM_TOOLBAR_LINE_ARROW, csDiagramView::OnToggleArrowToolUpdate)
+ EVT_UPDATE_UI(wxID_CUT, csDiagramView::OnCutUpdate)
+ EVT_UPDATE_UI(wxID_COPY, csDiagramView::OnCopyUpdate)
+ EVT_UPDATE_UI(wxID_CLEAR, csDiagramView::OnClearUpdate)
+ EVT_UPDATE_UI(wxID_PASTE, csDiagramView::OnPasteUpdate)
+ EVT_UPDATE_UI(wxID_DUPLICATE, csDiagramView::OnDuplicateUpdate)
+ EVT_UPDATE_UI(ID_CS_EDIT_PROPERTIES, csDiagramView::OnEditPropertiesUpdate)
+ EVT_UPDATE_UI(wxID_UNDO, csDiagramView::OnUndoUpdate)
+ EVT_UPDATE_UI(wxID_REDO, csDiagramView::OnRedoUpdate)
+END_EVENT_TABLE()
+
+// What to do when a view is created. Creates actual
+// windows for displaying the view.
+bool csDiagramView::OnCreate(wxDocument *doc, long flags)
+{
+ wxMenu* editMenu;
+ frame = wxGetApp().CreateChildFrame(doc, this, &editMenu);
+ canvas = wxGetApp().CreateCanvas(this, frame);
+ canvas->SetView(this);
+
+ SetFrame(frame);
+ Activate(TRUE);
+
+ // Initialize the edit menu Undo and Redo items
+ doc->GetCommandProcessor()->SetEditMenu(editMenu);
+ doc->GetCommandProcessor()->Initialize();
+
+ wxShapeCanvas *shapeCanvas = (wxShapeCanvas *)canvas;
+ csDiagramDocument *diagramDoc = (csDiagramDocument *)doc;
+ shapeCanvas->SetDiagram(diagramDoc->GetDiagram());
+ diagramDoc->GetDiagram()->SetCanvas(shapeCanvas);
+
+ diagramDoc->GetDiagram()->SetGridSpacing((double) wxGetApp().GetGridSpacing());
+
+ switch (wxGetApp().GetGridStyle())
+ {
+ case csGRID_STYLE_NONE:
+ {
+ diagramDoc->GetDiagram()->SetSnapToGrid(FALSE);
+ break;
+ }
+ case csGRID_STYLE_INVISIBLE:
+ {
+ diagramDoc->GetDiagram()->SetSnapToGrid(TRUE);
+ break;
+ }
+ case csGRID_STYLE_DOTTED:
+ {
+ // TODO (not implemented in OGL)
+ break;
+ }
+ }
+
+
+ return TRUE;
+}
+
+csDiagramView::~csDiagramView(void)
+{
+ if (frame)
+ {
+ ((wxDocMDIChildFrame*)frame)->SetView(NULL);
+ }
+}
+
+// Sneakily gets used for default print/preview
+// as well as drawing on the screen.
+void csDiagramView::OnDraw(wxDC *dc)
+{
+}
+
+void csDiagramView::OnUpdate(wxView *sender, wxObject *hint)
+{
+ if (canvas)
+ canvas->Refresh();
+}
+
+// Clean up windows used for displaying the view.
+bool csDiagramView::OnClose(bool deleteWindow)
+{
+ if (!GetDocument()->Close())
+ return FALSE;
+
+ csDiagramDocument *diagramDoc = (csDiagramDocument *)GetDocument();
+ diagramDoc->GetDiagram()->SetCanvas(NULL);
+
+ canvas->Clear();
+ canvas->SetDiagram(NULL);
+ canvas->SetView(NULL);
+ canvas = NULL;
+
+ wxMenu* fileMenu = frame->GetMenuBar()->GetMenu(0);
+
+ // Remove file menu from those managed by the command history
+ wxGetApp().GetDocManager()->FileHistoryRemoveMenu(fileMenu);
+
+ Activate(FALSE);
+ frame->Show(FALSE);
+
+ if (deleteWindow)
+ {
+ frame->Destroy();
+ }
+
+ return TRUE;
+}
+
+// Adds or removes shape from m_selections
+void csDiagramView::SelectShape(wxShape* shape, bool select)
+{
+ if (select && !m_selections.Member(shape))
+ m_selections.Append(shape);
+ else if (!select)
+ m_selections.DeleteObject(shape);
+}
+
+void csDiagramView::OnSelectAll(wxCommandEvent& event)
+{
+ SelectAll(TRUE);
+}
+
+wxShape *csDiagramView::FindFirstSelectedShape(void)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+ wxShape *theShape = NULL;
+ wxNode *node = doc->GetDiagram()->GetShapeList()->First();
+ while (node)
+ {
+ wxShape *eachShape = (wxShape *)node->Data();
+ if ((eachShape->GetParent() == NULL) && !eachShape->IsKindOf(CLASSINFO(wxLabelShape)) && eachShape->Selected())
+ {
+ theShape = eachShape;
+ node = NULL;
+ }
+ else node = node->Next();
+ }
+ return theShape;
+}
+
+void csDiagramView::FindSelectedShapes(wxList& selections, wxClassInfo* toFind)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+ wxNode *node = doc->GetDiagram()->GetShapeList()->First();
+ while (node)
+ {
+ wxShape *eachShape = (wxShape *)node->Data();
+ if ((eachShape->GetParent() == NULL) && !eachShape->IsKindOf(CLASSINFO(wxLabelShape)) && eachShape->Selected() && ((toFind == NULL) || (eachShape->IsKindOf(toFind))))
+ {
+ selections.Append(eachShape);
+ }
+ node = node->Next();
+ }
+}
+
+void csDiagramView::OnUndoUpdate(wxUpdateUIEvent& event)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+ event.Enable(doc->GetCommandProcessor()->CanUndo());
+}
+
+void csDiagramView::OnRedoUpdate(wxUpdateUIEvent& event)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+ event.Enable(doc->GetCommandProcessor()->CanRedo());
+}
+
+void csDiagramView::OnCut(wxCommandEvent& event)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+
+ // Copy the shapes to the clipboard
+ wxGetApp().GetDiagramClipboard().Copy(doc->GetDiagram());
+
+ wxList selections;
+ FindSelectedShapes(selections);
+
+ DoCut(selections);
+}
+
+void csDiagramView::OnClear(wxCommandEvent& event)
+{
+ wxList selections;
+ FindSelectedShapes(selections);
+
+ DoCut(selections);
+}
+
+void csDiagramView::OnCopy(wxCommandEvent& event)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+
+ // Copy the shapes to the clipboard
+ if (wxGetApp().GetDiagramClipboard().Copy(doc->GetDiagram()))
+ {
+#ifdef __WXMSW__
+ // Copy to the Windows clipboard
+ wxGetApp().GetDiagramClipboard().CopyToClipboard(1.0);
+#endif
+ }
+}
+
+void csDiagramView::OnPaste(wxCommandEvent& event)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+
+ wxGetApp().GetDiagramClipboard().Paste(doc->GetDiagram());
+}
+
+void csDiagramView::OnDuplicate(wxCommandEvent& event)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+
+ // Do a copy, then a paste
+ wxGetApp().GetDiagramClipboard().Copy(doc->GetDiagram());
+
+ // Apply an offset. Really, this offset should keep being incremented,
+ // but where do we reset it again?
+ wxGetApp().GetDiagramClipboard().Paste(doc->GetDiagram(), NULL, 20, 20);
+}
+
+void csDiagramView::OnCutUpdate(wxUpdateUIEvent& event)
+{
+ event.Enable( (m_selections.Number() > 0) );
+}
+
+void csDiagramView::OnClearUpdate(wxUpdateUIEvent& event)
+{
+ event.Enable( (m_selections.Number() > 0) );
+}
+
+void csDiagramView::OnCopyUpdate(wxUpdateUIEvent& event)
+{
+ event.Enable( (m_selections.Number() > 0) );
+}
+
+void csDiagramView::OnPasteUpdate(wxUpdateUIEvent& event)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+
+ int n = wxGetApp().GetDiagramClipboard().GetCount();
+
+ event.Enable( (n > 0) );
+}
+
+void csDiagramView::OnDuplicateUpdate(wxUpdateUIEvent& event)
+{
+ event.Enable( (m_selections.Number() > 0) );
+}
+
+void csDiagramView::DoCut(wxList& shapes)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+
+ if (shapes.Number() > 0)
+ {
+ csDiagramCommand* cmd = new csDiagramCommand("Cut", doc);
+
+ wxNode* node = shapes.First();
+ while (node)
+ {
+ wxShape *theShape = (wxShape*) node->Data();
+ csCommandState* state = new csCommandState(ID_CS_CUT, NULL, theShape);
+
+ // Insert lines at the front, so they are cut first.
+ // Otherwise we may try to remove a shape with a line still
+ // attached.
+ if (theShape->IsKindOf(CLASSINFO(wxLineShape)))
+ cmd->InsertState(state);
+ else
+ cmd->AddState(state);
+
+ node = node->Next();
+ }
+ cmd->RemoveLines(); // Schedule any connected lines, not already mentioned,
+ // to be removed first
+
+ doc->GetCommandProcessor()->Submit(cmd);
+ }
+}
+
+// Generalised command
+void csDiagramView::DoCmd(wxList& shapes, wxList& oldShapes, int cmd, const wxString& op)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+
+ if (shapes.Number() > 0)
+ {
+ csDiagramCommand* command = new csDiagramCommand(op, doc);
+
+ wxNode* node = shapes.First();
+ wxNode* node1 = oldShapes.First();
+ while (node && node1)
+ {
+ wxShape *theShape = (wxShape*) node->Data();
+ wxShape *oldShape = (wxShape*) node1->Data();
+ csCommandState* state = new csCommandState(cmd, theShape, oldShape);
+ command->AddState(state);
+
+ node = node->Next();
+ node1 = node1->Next();
+ }
+ doc->GetCommandProcessor()->Submit(command);
+ }
+}
+
+void csDiagramView::OnChangeBackgroundColour(wxCommandEvent& event)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+
+ wxList selections;
+ FindSelectedShapes(selections);
+
+ if (selections.Number() > 0)
+ {
+ wxColourData data;
+ data.SetChooseFull(TRUE);
+ if (selections.Number() == 1)
+ {
+ wxShape* firstShape = (wxShape*) selections.First()->Data();
+ data.SetColour(firstShape->GetBrush()->GetColour());
+ }
+
+ wxColourDialog *dialog = new wxColourDialog(frame, &data);
+ wxBrush *theBrush = NULL;
+ if (dialog->ShowModal() == wxID_OK)
+ {
+ wxColourData retData = dialog->GetColourData();
+ wxColour col = retData.GetColour();
+ theBrush = wxTheBrushList->FindOrCreateBrush(col, wxSOLID);
+ }
+ dialog->Close(TRUE);
+ if (!theBrush)
+ return;
+
+ csDiagramCommand* cmd = new csDiagramCommand("Change colour", doc);
+
+ wxNode* node = selections.First();
+ while (node)
+ {
+ wxShape *theShape = (wxShape*) node->Data();
+ wxShape* newShape = theShape->CreateNewCopy();
+ newShape->SetBrush(theBrush);
+
+ csCommandState* state = new csCommandState(ID_CS_CHANGE_BACKGROUND_COLOUR, newShape, theShape);
+ cmd->AddState(state);
+
+ node = node->Next();
+ }
+ doc->GetCommandProcessor()->Submit(cmd);
+ }
+}
+
+void csDiagramView::OnEditProperties(wxCommandEvent& event)
+{
+ wxShape *theShape = FindFirstSelectedShape();
+ if (theShape)
+ ((csEvtHandler *)theShape->GetEventHandler())->EditProperties();
+}
+
+void csDiagramView::OnEditPropertiesUpdate(wxUpdateUIEvent& event)
+{
+ wxList selections;
+ FindSelectedShapes(selections);
+ event.Enable( (selections.Number() > 0) );
+}
+
+void csDiagramView::OnPointSizeComboSel(wxCommandEvent& event)
+{
+ wxComboBox* combo = (wxComboBox*) event.GetEventObject();
+ wxASSERT( combo != NULL );
+
+ int newPointSize = (combo->GetSelection() + 1);
+
+ ApplyPointSize(newPointSize);
+
+}
+
+// TODO: must find out how to intercept the Return key, rather than
+// every key stroke. But for now, do every key stroke.
+void csDiagramView::OnPointSizeComboText(wxCommandEvent& event)
+{
+ wxComboBox* combo = (wxComboBox*) event.GetEventObject();
+ wxASSERT( combo != NULL );
+
+ wxString str(combo->GetValue());
+ int newPointSize = atoi((const char*) str);
+
+ if (newPointSize < 2)
+ return;
+
+ ApplyPointSize(newPointSize);
+}
+
+void csDiagramView::ApplyPointSize(int pointSize)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+
+ wxList selections;
+ FindSelectedShapes(selections);
+
+ if (selections.Number() > 0)
+ {
+ csDiagramCommand* cmd = new csDiagramCommand("Point size", doc);
+
+ wxNode* node = selections.First();
+ while (node)
+ {
+ wxShape *theShape = (wxShape*) node->Data();
+ wxShape *newShape = theShape->CreateNewCopy();
+
+ wxFont* newFont = wxTheFontList->FindOrCreateFont(pointSize,
+ theShape->GetFont()->GetFamily(),
+ theShape->GetFont()->GetStyle(),
+ theShape->GetFont()->GetWeight(),
+ theShape->GetFont()->GetUnderlined(),
+ theShape->GetFont()->GetFaceName());
+
+ newShape->SetFont(newFont);
+
+ csCommandState* state = new csCommandState(ID_CS_FONT_CHANGE, newShape, theShape);
+
+ cmd->AddState(state);
+
+ node = node->Next();
+ }
+ doc->GetCommandProcessor()->Submit(cmd);
+ }
+}
+
+void csDiagramView::OnZoomSel(wxCommandEvent& event)
+{
+ int maxZoom = 200;
+ int minZoom = 5;
+ int inc = 5;
+ int noStrings = (maxZoom - minZoom)/inc ;
+
+ wxComboBox* combo = (wxComboBox*) event.GetEventObject();
+ wxASSERT( combo != NULL );
+
+ int scale = (int) ((noStrings - combo->GetSelection() - 1)*inc + minZoom);
+
+ canvas->SetScale((double) (scale/100.0), (double) (scale/100.0));
+ canvas->Refresh();
+}
+
+// Select or deselect all
+void csDiagramView::SelectAll(bool select)
+{
+ wxClientDC dc(canvas);
+ canvas->PrepareDC(dc);
+
+ if (!select)
+ {
+ wxList selections;
+ FindSelectedShapes(selections);
+
+ wxNode* node = selections.First();
+ while (node)
+ {
+ wxShape *theShape = (wxShape*) node->Data();
+ theShape->Select(FALSE, &dc);
+ SelectShape(theShape, FALSE);
+
+ node = node->Next();
+ }
+ }
+ else
+ {
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+ wxNode *node = doc->GetDiagram()->GetShapeList()->First();
+ while (node)
+ {
+ wxShape *eachShape = (wxShape *)node->Data();
+ if (eachShape->GetParent() == NULL &&
+ !eachShape->IsKindOf(CLASSINFO(wxControlPoint)) &&
+ !eachShape->IsKindOf(CLASSINFO(wxLabelShape)))
+ {
+ eachShape->Select(TRUE, &dc);
+ SelectShape(eachShape, TRUE);
+ }
+ node = node->Next();
+ }
+ }
+}
+
+
+void csDiagramView::OnToggleArrowTool(wxCommandEvent& event)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+
+ bool state = wxGetApp().GetDiagramToolBar()->GetToolState(DIAGRAM_TOOLBAR_LINE_ARROW);
+ wxString stateName;
+ if (state)
+ stateName = "Arrow on";
+ else
+ stateName = "Arrow off";
+
+ wxList selections;
+ FindSelectedShapes(selections, CLASSINFO(wxLineShape));
+
+ if (selections.Number() > 0)
+ {
+ csDiagramCommand* cmd = new csDiagramCommand(stateName, doc);
+
+ wxNode* node = selections.First();
+ while (node)
+ {
+ wxLineShape *theShape = (wxLineShape*) node->Data();
+ wxLineShape *newShape = NULL;
+
+ if (state)
+ {
+ // Add arrow
+ if (theShape->GetArrows().Number() == 0)
+ {
+ newShape = (wxLineShape*) theShape->CreateNewCopy();
+ newShape->AddArrow(ARROW_ARROW, ARROW_POSITION_MIDDLE, 10.0, 0.0, "Normal arrowhead");
+ }
+ }
+ else
+ {
+ if (theShape->GetArrows().Number() > 0)
+ {
+ newShape = (wxLineShape*) theShape->CreateNewCopy();
+ newShape->ClearArrowsAtPosition();
+ }
+ }
+
+ // If the new state is the same as the old, don't bother adding it to the command state.
+ if (newShape)
+ {
+ csCommandState* state = new csCommandState(ID_CS_ARROW_CHANGE, newShape, theShape);
+ cmd->AddState(state);
+ }
+
+ node = node->Next();
+ }
+ doc->GetCommandProcessor()->Submit(cmd);
+ }
+}
+
+void csDiagramView::OnToggleArrowToolUpdate(wxUpdateUIEvent& event)
+{
+ wxList selections;
+ FindSelectedShapes(selections, CLASSINFO(wxLineShape));
+ event.Enable( (selections.Number() > 0) );
+}
+
+// Make the point size combobox reflect this
+void csDiagramView::ReflectPointSize(int pointSize)
+{
+ wxComboBox* comboBox = wxGetApp().GetPointSizeComboBox();
+ comboBox->SetSelection(pointSize -1);
+}
+
+// Make the arrow toggle button reflect the state of the line
+void csDiagramView::ReflectArrowState(wxLineShape* lineShape)
+{
+ bool haveArrow = FALSE;
+ wxNode *node = lineShape->GetArrows().First();
+ while (node)
+ {
+ wxArrowHead *arrow = (wxArrowHead *)node->Data();
+ if (ARROW_POSITION_MIDDLE == arrow->GetArrowEnd())
+ haveArrow = TRUE;
+ node = node->Next();
+ }
+
+ wxGetApp().GetDiagramToolBar()->ToggleTool(DIAGRAM_TOOLBAR_LINE_ARROW, haveArrow);
+}
+
+void csDiagramView::OnAlign(wxCommandEvent& event)
+{
+ // Make a copy of the selections, keeping only those shapes
+ // that are top-level non-line shapes.
+ wxList selections;
+ wxNode* node = GetSelectionList().First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if ((shape->GetParent() == NULL) && (!shape->IsKindOf(CLASSINFO(wxLineShape))))
+ {
+ selections.Append(shape);
+ }
+ node = node->Next();
+ }
+
+ if (selections.Number() == 0)
+ return;
+
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+ csDiagramCommand* cmd = new csDiagramCommand("Align", doc);
+
+ node = selections.First();
+ wxShape* firstShape = (wxShape*) node->Data();
+
+ double x = firstShape->GetX();
+ double y = firstShape->GetY();
+ double width, height;
+ firstShape->GetBoundingBoxMax(&width, &height);
+
+ node = selections.First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (shape != firstShape)
+ {
+ double x1 = shape->GetX();
+ double y1 = shape->GetY();
+ double width1, height1;
+ shape->GetBoundingBoxMax(& width1, & height1);
+
+ wxShape* newShape = shape->CreateNewCopy();
+
+ switch (event.GetId())
+ {
+ case DIAGRAM_TOOLBAR_ALIGNL:
+ {
+ double x2 = (double)(x - (width/2.0) + (width1/2.0));
+ newShape->SetX(x2);
+ break;
+ }
+ case DIAGRAM_TOOLBAR_ALIGNR:
+ {
+ double x2 = (double)(x + (width/2.0) - (width1/2.0));
+ newShape->SetX(x2);
+ break;
+ }
+ case DIAGRAM_TOOLBAR_ALIGNB:
+ {
+ double y2 = (double)(y + (height/2.0) - (height1/2.0));
+ newShape->SetY(y2);
+ break;
+ }
+ case DIAGRAM_TOOLBAR_ALIGNT:
+ {
+ double y2 = (double)(y - (height/2.0) + (height1/2.0));
+ newShape->SetY(y2);
+ break;
+ }
+ case DIAGRAM_TOOLBAR_ALIGN_HORIZ:
+ {
+ newShape->SetX(x);
+ break;
+ }
+ case DIAGRAM_TOOLBAR_ALIGN_VERT:
+ {
+ newShape->SetY(y);
+ break;
+ }
+ case DIAGRAM_TOOLBAR_COPY_SIZE:
+ {
+ newShape->SetSize(width, height);
+ break;
+ }
+ }
+ csCommandState* state = new csCommandState(ID_CS_ALIGN, newShape, shape);
+ cmd->AddState(state);
+ }
+ node = node->Next();
+ }
+ doc->GetCommandProcessor()->Submit(cmd);
+}
+
+void csDiagramView::OnAlignUpdate(wxUpdateUIEvent& event)
+{
+ // This is an approximation, since there may be lines
+ // amongst the selections.
+ event.Enable( (m_selections.Number() > 1) ) ;
+}
+
+void csDiagramView::OnNewLinePoint(wxCommandEvent& event)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+ csDiagramCommand* cmd = new csDiagramCommand("New line point", doc);
+
+ wxNode* node = m_selections.First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (shape->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ wxShape* newShape = shape->CreateNewCopy();
+ ((wxLineShape*)newShape)->InsertLineControlPoint(NULL);
+ csCommandState* state = new csCommandState(ID_CS_NEW_POINT, newShape, shape);
+ cmd->AddState(state);
+ }
+ node = node->Next();
+ }
+ doc->GetCommandProcessor()->Submit(cmd);
+}
+
+void csDiagramView::OnCutLinePoint(wxCommandEvent& event)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+ csDiagramCommand* cmd = new csDiagramCommand("Cut line point", doc);
+
+ wxNode* node = m_selections.First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (shape->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ wxShape* newShape = shape->CreateNewCopy();
+ ((wxLineShape*)newShape)->DeleteLineControlPoint();
+ csCommandState* state = new csCommandState(ID_CS_CUT_POINT, newShape, shape);
+ cmd->AddState(state);
+ }
+ node = node->Next();
+ }
+ doc->GetCommandProcessor()->Submit(cmd);
+}
+
+void csDiagramView::OnStraightenLines(wxCommandEvent& event)
+{
+ csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
+ csDiagramCommand* cmd = new csDiagramCommand("Straighten lines", doc);
+
+ wxNode* node = m_selections.First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (shape->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ wxShape* newShape = shape->CreateNewCopy();
+ ((wxLineShape*)newShape)->Straighten();
+ csCommandState* state = new csCommandState(ID_CS_STRAIGHTEN, newShape, shape);
+ cmd->AddState(state);
+ }
+ node = node->Next();
+ }
+ doc->GetCommandProcessor()->Submit(cmd);
+}
+
+void csDiagramView::OnNewLinePointUpdate(wxUpdateUIEvent& event)
+{
+ wxList selections;
+ FindSelectedShapes(selections, CLASSINFO(wxLineShape));
+ event.Enable( (selections.Number() > 0) );
+}
+
+void csDiagramView::OnCutLinePointUpdate(wxUpdateUIEvent& event)
+{
+ wxList selections;
+ FindSelectedShapes(selections, CLASSINFO(wxLineShape));
+ event.Enable( (selections.Number() > 0) );
+}
+
+void csDiagramView::OnStraightenLinesUpdate(wxUpdateUIEvent& event)
+{
+ wxList selections;
+ FindSelectedShapes(selections, CLASSINFO(wxLineShape));
+ event.Enable( (selections.Number() > 0) );
+}
+
+/*
+ * Window implementations
+ */
+
+IMPLEMENT_CLASS(csCanvas, wxShapeCanvas)
+
+BEGIN_EVENT_TABLE(csCanvas, wxShapeCanvas)
+ EVT_MOUSE_EVENTS(csCanvas::OnMouseEvent)
+ EVT_PAINT(csCanvas::OnPaint)
+END_EVENT_TABLE()
+
+// Define a constructor for my canvas
+csCanvas::csCanvas(csDiagramView *v, wxWindow *parent, wxWindowID id, const wxPoint& pos,
+ const wxSize& size, long style):
+ wxShapeCanvas(parent, id, pos, size, style)
+{
+ m_view = v;
+}
+
+csCanvas::~csCanvas(void)
+{
+}
+
+void csCanvas::DrawOutline(wxDC& dc, double x1, double y1, double x2, double y2)
+{
+ wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
+ dc.SetPen(dottedPen);
+ dc.SetBrush(* wxTRANSPARENT_BRUSH);
+
+ dc.DrawRectangle((long) x1, (long) y1, (long) (x2 - x1), (long) (y2 - y1));
+}
+
+void csCanvas::OnLeftClick(double x, double y, int keys)
+{
+ csEditorToolPalette *palette = wxGetApp().GetDiagramPalette();
+
+ if (palette->GetSelection() == PALETTE_ARROW)
+ {
+ GetView()->SelectAll(FALSE);
+
+ wxClientDC dc(this);
+ PrepareDC(dc);
+
+ Redraw(dc);
+ return;
+ }
+
+ if (palette->GetSelection() == PALETTE_TEXT_TOOL)
+ {
+ // Ask for a label and create a new free-floating text region
+ csLabelEditingDialog* dialog = new csLabelEditingDialog(GetParent());
+
+ dialog->SetShapeLabel("");
+ dialog->SetTitle("New text box");
+ if (dialog->ShowModal() == wxID_CANCEL)
+ {
+ dialog->Destroy();
+ return;
+ }
+
+ wxString newLabel = dialog->GetShapeLabel();
+ dialog->Destroy();
+
+ wxShape* shape = new csTextBoxShape;
+ shape->AssignNewIds();
+ shape->SetEventHandler(new csEvtHandler(shape, shape, newLabel));
+
+ wxComboBox* comboBox = wxGetApp().GetPointSizeComboBox();
+ wxString str(comboBox->GetValue());
+ int pointSize = atoi((const char*) str);
+
+ wxFont* newFont = wxTheFontList->FindOrCreateFont(pointSize,
+ shape->GetFont()->GetFamily(),
+ shape->GetFont()->GetStyle(),
+ shape->GetFont()->GetWeight(),
+ shape->GetFont()->GetUnderlined(),
+ shape->GetFont()->GetFaceName());
+
+ shape->SetFont(newFont);
+
+ shape->SetX(x);
+ shape->SetY(y);
+
+ csDiagramCommand* cmd = new csDiagramCommand("Text box",
+ (csDiagramDocument *)GetView()->GetDocument(),
+ new csCommandState(ID_CS_ADD_SHAPE, shape, NULL));
+ GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd);
+
+ palette->SetSelection(PALETTE_ARROW);
+
+ return;
+ }
+
+ csSymbol* symbol = wxGetApp().GetSymbolDatabase()->FindSymbol(palette->GetSelection());
+ if (symbol)
+ {
+ wxShape* theShape = symbol->GetShape()->CreateNewCopy();
+
+ wxComboBox* comboBox = wxGetApp().GetPointSizeComboBox();
+ wxString str(comboBox->GetValue());
+ int pointSize = atoi((const char*) str);
+
+ wxFont* newFont = wxTheFontList->FindOrCreateFont(pointSize,
+ symbol->GetShape()->GetFont()->GetFamily(),
+ symbol->GetShape()->GetFont()->GetStyle(),
+ symbol->GetShape()->GetFont()->GetWeight(),
+ symbol->GetShape()->GetFont()->GetUnderlined(),
+ symbol->GetShape()->GetFont()->GetFaceName());
+
+ theShape->SetFont(newFont);
+
+ theShape->AssignNewIds();
+ theShape->SetX(x);
+ theShape->SetY(y);
+
+ csDiagramCommand* cmd = new csDiagramCommand(symbol->GetName(),
+ (csDiagramDocument *)GetView()->GetDocument(),
+ new csCommandState(ID_CS_ADD_SHAPE, theShape, NULL));
+ GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd);
+
+ palette->SetSelection(PALETTE_ARROW);
+ }
+}
+
+void csCanvas::OnRightClick(double x, double y, int keys)
+{
+}
+
+// Initial point
+static double sg_initialX, sg_initialY;
+
+void csCanvas::OnDragLeft(bool draw, double x, double y, int keys)
+{
+ wxClientDC dc(this);
+ PrepareDC(dc);
+
+ dc.SetLogicalFunction(wxXOR);
+ DrawOutline(dc, sg_initialX, sg_initialY, x, y);
+}
+
+void csCanvas::OnBeginDragLeft(double x, double y, int keys)
+{
+ sg_initialX = x;
+ sg_initialY = y;
+
+ wxClientDC dc(this);
+ PrepareDC(dc);
+
+ dc.SetLogicalFunction(wxXOR);
+ DrawOutline(dc, sg_initialX, sg_initialY, x, y);
+ CaptureMouse();
+}
+
+void csCanvas::OnEndDragLeft(double x, double y, int keys)
+{
+ ReleaseMouse();
+
+ wxClientDC dc(this);
+ PrepareDC(dc);
+
+ // Select all images within the rectangle
+ float min_x, max_x, min_y, max_y;
+ min_x = wxMin(x, sg_initialX);
+ max_x = wxMax(x, sg_initialX);
+ min_y = wxMin(y, sg_initialY);
+ max_y = wxMax(y, sg_initialY);
+
+ wxNode *node = GetDiagram()->GetShapeList()->First();
+ while (node)
+ {
+ wxShape *shape = (wxShape *)node->Data();
+ if (shape->GetParent() == NULL && !shape->IsKindOf(CLASSINFO(wxControlPoint)))
+ {
+ float image_x = shape->GetX();
+ float image_y = shape->GetY();
+ if (image_x >= min_x && image_x <= max_x &&
+ image_y >= min_y && image_y <= max_y)
+ {
+ shape->Select(TRUE, &dc);
+ GetView()->SelectShape(shape, TRUE);
+ }
+ }
+ node = node->Next();
+ }
+}
+
+void csCanvas::OnDragRight(bool draw, double x, double y, int keys)
+{
+}
+
+void csCanvas::OnBeginDragRight(double x, double y, int keys)
+{
+}
+
+void csCanvas::OnEndDragRight(double x, double y, int keys)
+{
+}
+
+void csCanvas::OnMouseEvent(wxMouseEvent& event)
+{
+ wxShapeCanvas::OnMouseEvent(event);
+}
+
+void csCanvas::OnPaint(wxPaintEvent& event)
+{
+// if (GetDiagram())
+ wxShapeCanvas::OnPaint(event);
+}
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: view.h
+// Purpose: View-related classes
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _STUDIO_VIEW_H_
+#define _STUDIO_VIEW_H_
+
+#ifdef __GNUG__
+// #pragma interface "view.h"
+#endif
+
+#include "doc.h"
+#include "ogl.h"
+
+class csDiagramView;
+class csCanvas: public wxShapeCanvas
+{
+DECLARE_CLASS(csCanvas)
+ public:
+
+ csCanvas(csDiagramView *view, wxWindow *parent = NULL, wxWindowID id = -1,
+ const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
+ long style = wxRETAINED);
+ ~csCanvas(void);
+
+ void DrawOutline(wxDC& dc, double x1, double y1, double x2, double y2);
+
+ void OnMouseEvent(wxMouseEvent& event);
+ void OnPaint(wxPaintEvent& event);
+
+ virtual void OnLeftClick(double x, double y, int keys = 0);
+ virtual void OnRightClick(double x, double y, int keys = 0);
+
+ virtual void OnDragLeft(bool draw, double x, double y, int keys=0); // Erase if draw false
+ virtual void OnBeginDragLeft(double x, double y, int keys=0);
+ virtual void OnEndDragLeft(double x, double y, int keys=0);
+
+ virtual void OnDragRight(bool draw, double x, double y, int keys=0); // Erase if draw false
+ virtual void OnBeginDragRight(double x, double y, int keys=0);
+ virtual void OnEndDragRight(double x, double y, int keys=0);
+
+ inline csDiagramView* GetView() const { return m_view; }
+ inline void SetView(csDiagramView* view) { m_view = view; }
+
+ protected:
+ csDiagramView* m_view;
+
+DECLARE_EVENT_TABLE()
+};
+
+class csDiagramView: public wxView
+{
+ DECLARE_DYNAMIC_CLASS(csDiagramView)
+ public:
+ csDiagramView(void) { canvas = NULL; frame = NULL; };
+ ~csDiagramView(void);
+
+ bool OnCreate(wxDocument *doc, long flags);
+ void OnDraw(wxDC *dc);
+ void OnUpdate(wxView *sender, wxObject *hint = NULL);
+ bool OnClose(bool deleteWindow = TRUE);
+ void OnSelectAll(wxCommandEvent& event);
+
+ wxShape *FindFirstSelectedShape(void);
+
+ // Scans the canvas for selections (doesn't use m_selections)
+ void FindSelectedShapes(wxList& selections, wxClassInfo* toFind = NULL);
+
+ // The selections in the order in which they were selected
+ inline wxList& GetSelectionList() const { return (wxList&) m_selections; }
+
+ // Adds or removes shape from m_selections
+ void SelectShape(wxShape* shape, bool select);
+
+ // Apply point size to current shapes
+ void ApplyPointSize(int pointSize);
+
+ // Make the point size combobox reflect this
+ void ReflectPointSize(int pointSize);
+
+ // Make the arrow toggle button reflect the state of the line
+ void ReflectArrowState(wxLineShape* lineShape);
+
+ // Do a cut operation for the given list of shapes
+ void DoCut(wxList& shapes);
+
+ // Do a general command
+ void DoCmd(wxList& shapes, wxList& oldShapes, int cmd, const wxString& op);
+
+ // Select or deselect all
+ void SelectAll(bool select = TRUE);
+
+// Event handlers
+ void OnCut(wxCommandEvent& event);
+ void OnCopy(wxCommandEvent& event);
+ void OnPaste(wxCommandEvent& event);
+ void OnDuplicate(wxCommandEvent& event);
+ void OnClear(wxCommandEvent& event);
+ void OnChangeBackgroundColour(wxCommandEvent& event);
+ void OnEditProperties(wxCommandEvent& event);
+ void OnPointSizeComboSel(wxCommandEvent& event);
+ void OnPointSizeComboText(wxCommandEvent& event);
+ void OnToggleArrowTool(wxCommandEvent& event);
+ void OnZoomSel(wxCommandEvent& event);
+ void OnAlign(wxCommandEvent& event);
+ void OnNewLinePoint(wxCommandEvent& event);
+ void OnCutLinePoint(wxCommandEvent& event);
+ void OnStraightenLines(wxCommandEvent& event);
+
+// UI update handles
+ void OnToggleArrowToolUpdate(wxUpdateUIEvent& event);
+ void OnEditPropertiesUpdate(wxUpdateUIEvent& event);
+ void OnCutUpdate(wxUpdateUIEvent& event);
+ void OnClearUpdate(wxUpdateUIEvent& event);
+ void OnCopyUpdate(wxUpdateUIEvent& event);
+ void OnPasteUpdate(wxUpdateUIEvent& event);
+ void OnDuplicateUpdate(wxUpdateUIEvent& event);
+ void OnAlignUpdate(wxUpdateUIEvent& event);
+ void OnNewLinePointUpdate(wxUpdateUIEvent& event);
+ void OnCutLinePointUpdate(wxUpdateUIEvent& event);
+ void OnStraightenLinesUpdate(wxUpdateUIEvent& event);
+ void OnUndoUpdate(wxUpdateUIEvent& event);
+ void OnRedoUpdate(wxUpdateUIEvent& event);
+
+DECLARE_EVENT_TABLE()
+
+public:
+ wxFrame* frame;
+ csCanvas* canvas;
+ wxList m_selections;
+};
+
+#endif
+ // _STUDIO_VIEW_H_
/* Metafile Functions */
/* Win32s/Borland need these macros, although META_SETBKCOLOR is defined */
-#if !defined(META_SETBKCOLOR) // || defined(WIN32)
+#if 1 // !defined(META_SETBKCOLOR) // || defined(WIN32)
#define META_SETBKCOLOR 0x0201
#define META_SETBKMODE 0x0102