| 1 | ///////////////////////////////////////////////////////////////////////////// |
| 2 | // Name: view.cpp |
| 3 | // Purpose: View classes |
| 4 | // Author: Julian Smart |
| 5 | // Modified by: |
| 6 | // Created: 04/01/98 |
| 7 | // RCS-ID: $Id$ |
| 8 | // Copyright: (c) Julian Smart and Markus Holzem |
| 9 | // Licence: wxWindows license |
| 10 | ///////////////////////////////////////////////////////////////////////////// |
| 11 | |
| 12 | #ifdef __GNUG__ |
| 13 | // #pragma implementation |
| 14 | #endif |
| 15 | |
| 16 | // For compilers that support precompilation, includes "wx/wx.h". |
| 17 | #include "wx/wxprec.h" |
| 18 | |
| 19 | #ifdef __BORLANDC__ |
| 20 | #pragma hdrstop |
| 21 | #endif |
| 22 | |
| 23 | #ifndef WX_PRECOMP |
| 24 | #include "wx/wx.h" |
| 25 | #endif |
| 26 | |
| 27 | #if !wxUSE_DOC_VIEW_ARCHITECTURE |
| 28 | #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h! |
| 29 | #endif |
| 30 | |
| 31 | #include "docview.h" |
| 32 | #include "doc.h" |
| 33 | #include "view.h" |
| 34 | |
| 35 | IMPLEMENT_DYNAMIC_CLASS(DrawingView, wxView) |
| 36 | |
| 37 | // For drawing lines in a canvas |
| 38 | float xpos = -1; |
| 39 | float ypos = -1; |
| 40 | |
| 41 | BEGIN_EVENT_TABLE(DrawingView, wxView) |
| 42 | EVT_MENU(DOODLE_CUT, DrawingView::OnCut) |
| 43 | END_EVENT_TABLE() |
| 44 | |
| 45 | // What to do when a view is created. Creates actual |
| 46 | // windows for displaying the view. |
| 47 | bool DrawingView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) |
| 48 | { |
| 49 | if (!singleWindowMode) |
| 50 | { |
| 51 | // Multiple windows |
| 52 | frame = wxGetApp().CreateChildFrame(doc, this, TRUE); |
| 53 | frame->SetTitle("DrawingView"); |
| 54 | |
| 55 | canvas = GetMainFrame()->CreateCanvas(this, frame); |
| 56 | #ifdef __X__ |
| 57 | // X seems to require a forced resize |
| 58 | int x, y; |
| 59 | frame->GetSize(&x, &y); |
| 60 | frame->SetSize(-1, -1, x, y); |
| 61 | #endif |
| 62 | frame->Show(TRUE); |
| 63 | } |
| 64 | else |
| 65 | { |
| 66 | // Single-window mode |
| 67 | frame = GetMainFrame(); |
| 68 | canvas = GetMainFrame()->canvas; |
| 69 | canvas->view = this; |
| 70 | |
| 71 | // Associate the appropriate frame with this view. |
| 72 | SetFrame(frame); |
| 73 | |
| 74 | // Make sure the document manager knows that this is the |
| 75 | // current view. |
| 76 | Activate(TRUE); |
| 77 | |
| 78 | // Initialize the edit menu Undo and Redo items |
| 79 | doc->GetCommandProcessor()->SetEditMenu(((MyFrame *)frame)->editMenu); |
| 80 | doc->GetCommandProcessor()->Initialize(); |
| 81 | } |
| 82 | |
| 83 | return TRUE; |
| 84 | } |
| 85 | |
| 86 | // Sneakily gets used for default print/preview |
| 87 | // as well as drawing on the screen. |
| 88 | void DrawingView::OnDraw(wxDC *dc) |
| 89 | { |
| 90 | dc->SetFont(*wxNORMAL_FONT); |
| 91 | dc->SetPen(*wxBLACK_PEN); |
| 92 | |
| 93 | wxNode *node = ((DrawingDocument *)GetDocument())->GetDoodleSegments().First(); |
| 94 | while (node) |
| 95 | { |
| 96 | DoodleSegment *seg = (DoodleSegment *)node->Data(); |
| 97 | seg->Draw(dc); |
| 98 | node = node->Next(); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | void DrawingView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint)) |
| 103 | { |
| 104 | if (canvas) |
| 105 | canvas->Refresh(); |
| 106 | |
| 107 | /* Is the following necessary? |
| 108 | #ifdef __WXMSW__ |
| 109 | if (canvas) |
| 110 | canvas->Refresh(); |
| 111 | #else |
| 112 | if (canvas) |
| 113 | { |
| 114 | wxClientDC dc(canvas); |
| 115 | dc.Clear(); |
| 116 | OnDraw(& dc); |
| 117 | } |
| 118 | #endif |
| 119 | */ |
| 120 | } |
| 121 | |
| 122 | // Clean up windows used for displaying the view. |
| 123 | bool DrawingView::OnClose(bool deleteWindow) |
| 124 | { |
| 125 | if (!GetDocument()->Close()) |
| 126 | return FALSE; |
| 127 | |
| 128 | // Clear the canvas in case we're in single-window mode, |
| 129 | // and the canvas stays. |
| 130 | canvas->Clear(); |
| 131 | canvas->view = (wxView *) NULL; |
| 132 | canvas = (MyCanvas *) NULL; |
| 133 | |
| 134 | wxString s(wxTheApp->GetAppName()); |
| 135 | if (frame) |
| 136 | frame->SetTitle(s); |
| 137 | |
| 138 | SetFrame((wxFrame *) NULL); |
| 139 | |
| 140 | Activate(FALSE); |
| 141 | |
| 142 | if (deleteWindow && !singleWindowMode) |
| 143 | { |
| 144 | delete frame; |
| 145 | return TRUE; |
| 146 | } |
| 147 | return TRUE; |
| 148 | } |
| 149 | |
| 150 | void DrawingView::OnCut(wxCommandEvent& WXUNUSED(event) ) |
| 151 | { |
| 152 | DrawingDocument *doc = (DrawingDocument *)GetDocument(); |
| 153 | doc->GetCommandProcessor()->Submit(new DrawingCommand((char *) "Cut Last Segment", DOODLE_CUT, doc, (DoodleSegment *) NULL)); |
| 154 | } |
| 155 | |
| 156 | IMPLEMENT_DYNAMIC_CLASS(TextEditView, wxView) |
| 157 | |
| 158 | bool TextEditView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) |
| 159 | { |
| 160 | frame = wxGetApp().CreateChildFrame(doc, this, FALSE); |
| 161 | |
| 162 | int width, height; |
| 163 | frame->GetClientSize(&width, &height); |
| 164 | textsw = new MyTextWindow(this, frame, wxPoint(0, 0), wxSize(width, height), wxTE_MULTILINE); |
| 165 | frame->SetTitle("TextEditView"); |
| 166 | |
| 167 | #ifdef __X__ |
| 168 | // X seems to require a forced resize |
| 169 | int x, y; |
| 170 | frame->GetSize(&x, &y); |
| 171 | frame->SetSize(-1, -1, x, y); |
| 172 | #endif |
| 173 | |
| 174 | frame->Show(TRUE); |
| 175 | Activate(TRUE); |
| 176 | |
| 177 | return TRUE; |
| 178 | } |
| 179 | |
| 180 | // Handled by wxTextWindow |
| 181 | void TextEditView::OnDraw(wxDC *WXUNUSED(dc) ) |
| 182 | { |
| 183 | } |
| 184 | |
| 185 | void TextEditView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) ) |
| 186 | { |
| 187 | } |
| 188 | |
| 189 | bool TextEditView::OnClose(bool deleteWindow) |
| 190 | { |
| 191 | if (!GetDocument()->Close()) |
| 192 | return FALSE; |
| 193 | |
| 194 | Activate(FALSE); |
| 195 | |
| 196 | if (deleteWindow) |
| 197 | { |
| 198 | delete frame; |
| 199 | return TRUE; |
| 200 | } |
| 201 | return TRUE; |
| 202 | } |
| 203 | |
| 204 | /* |
| 205 | * Window implementations |
| 206 | */ |
| 207 | |
| 208 | BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) |
| 209 | EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent) |
| 210 | END_EVENT_TABLE() |
| 211 | |
| 212 | // Define a constructor for my canvas |
| 213 | MyCanvas::MyCanvas(wxView *v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style): |
| 214 | wxScrolledWindow(frame, -1, pos, size, style) |
| 215 | { |
| 216 | view = v; |
| 217 | } |
| 218 | |
| 219 | // Define the repainting behaviour |
| 220 | void MyCanvas::OnDraw(wxDC& dc) |
| 221 | { |
| 222 | if (view) |
| 223 | view->OnDraw(& dc); |
| 224 | } |
| 225 | |
| 226 | // This implements a tiny doodling program. Drag the mouse using |
| 227 | // the left button. |
| 228 | void MyCanvas::OnMouseEvent(wxMouseEvent& event) |
| 229 | { |
| 230 | if (!view) |
| 231 | return; |
| 232 | |
| 233 | static DoodleSegment *currentSegment = (DoodleSegment *) NULL; |
| 234 | |
| 235 | wxClientDC dc(this); |
| 236 | PrepareDC(dc); |
| 237 | |
| 238 | dc.SetPen(*wxBLACK_PEN); |
| 239 | |
| 240 | wxPoint pt(event.GetLogicalPosition(dc)); |
| 241 | |
| 242 | if (currentSegment && event.LeftUp()) |
| 243 | { |
| 244 | if (currentSegment->lines.Number() == 0) |
| 245 | { |
| 246 | delete currentSegment; |
| 247 | currentSegment = (DoodleSegment *) NULL; |
| 248 | } |
| 249 | else |
| 250 | { |
| 251 | // We've got a valid segment on mouse left up, so store it. |
| 252 | DrawingDocument *doc = (DrawingDocument *)view->GetDocument(); |
| 253 | |
| 254 | doc->GetCommandProcessor()->Submit(new DrawingCommand("Add Segment", DOODLE_ADD, doc, currentSegment)); |
| 255 | |
| 256 | view->GetDocument()->Modify(TRUE); |
| 257 | currentSegment = (DoodleSegment *) NULL; |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | if (xpos > -1 && ypos > -1 && event.Dragging()) |
| 262 | { |
| 263 | if (!currentSegment) |
| 264 | currentSegment = new DoodleSegment; |
| 265 | |
| 266 | DoodleLine *newLine = new DoodleLine; |
| 267 | newLine->x1 = (long)xpos; |
| 268 | newLine->y1 = (long)ypos; |
| 269 | newLine->x2 = pt.x; |
| 270 | newLine->y2 = pt.y; |
| 271 | currentSegment->lines.Append(newLine); |
| 272 | |
| 273 | dc.DrawLine( (long)xpos, (long)ypos, pt.x, pt.y); |
| 274 | } |
| 275 | xpos = pt.x; |
| 276 | ypos = pt.y; |
| 277 | } |
| 278 | |
| 279 | // Define a constructor for my text subwindow |
| 280 | MyTextWindow::MyTextWindow(wxView *v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style): |
| 281 | wxTextCtrl(frame, -1, "", pos, size, style) |
| 282 | { |
| 283 | view = v; |
| 284 | } |
| 285 | |
| 286 | |