1 /*-*- c++ -*-********************************************************
2 * wxLwindow.h : a scrolled Window for displaying/entering rich text*
4 * (C) 1998, 1999 by Karsten Ballüder (Ballueder@usa.net) *
7 *******************************************************************/
10 # pragma implementation "wxlwindow.h"
18 # include "gui/wxMenuDefs.h"
19 # include "gui/wxMApp.h"
21 # include "gui/wxlwindow.h"
29 # include "wxlwindow.h"
32 BEGIN_EVENT_TABLE(wxLayoutWindow
,wxScrolledWindow
)
33 EVT_PAINT (wxLayoutWindow::OnPaint
)
34 EVT_CHAR (wxLayoutWindow::OnChar
)
35 EVT_LEFT_DOWN(wxLayoutWindow::OnLeftMouseClick
)
36 EVT_RIGHT_DOWN(wxLayoutWindow::OnRightMouseClick
)
37 EVT_LEFT_DCLICK(wxLayoutWindow::OnMouseDblClick
)
38 EVT_MENU_RANGE(WXLOWIN_MENU_FIRST
, WXLOWIN_MENU_LAST
, wxLayoutWindow::OnMenu
)
39 EVT_SET_FOCUS(wxLayoutWindow::OnSetFocus
)
40 EVT_KILL_FOCUS(wxLayoutWindow::OnKillFocus
)
44 EVT_MENU(WXLOWIN_MENU_LARGER, wxLayoutWindow::OnMenu)
45 EVT_MENU(WXLOWIN_MENU_SMALLER, wxLayoutWindow::OnMenu)
46 EVT_MENU(WXLOWIN_MENU_UNDERLINE_ON, wxLayoutWindow::OnMenu)
47 EVT_MENU(WXLOWIN_MENU_UNDERLINE_OFF, wxLayoutWindow::OnMenu)
48 EVT_MENU(WXLOWIN_MENU_BOLD_ON, wxLayoutWindow::OnMenu)
49 EVT_MENU(WXLOWIN_MENU_BOLD_OFF, wxLayoutWindow::OnMenu)
50 EVT_MENU(WXLOWIN_MENU_ITALICS_ON, wxLayoutWindow::OnMenu)
51 EVT_MENU(WXLOWIN_MENU_ITALICS_OFF, wxLayoutWindow::OnMenu)
52 EVT_MENU(WXLOWIN_MENU_ROMAN, wxLayoutWindow::OnMenu)
53 EVT_MENU(WXLOWIN_MENU_TYPEWRITER, wxLayoutWindow::OnMenu)
54 EVT_MENU(WXLOWIN_MENU_SANSSERIF, wxLayoutWindow::OnMenu)
57 wxLayoutWindow::wxLayoutWindow(wxWindow
*parent
)
58 : wxScrolledWindow(parent
, -1, wxDefaultPosition
, wxDefaultSize
,
59 wxHSCROLL
| wxVSCROLL
| wxBORDER
)
63 m_doSendEvents
= false;
64 m_ViewStartX
= 0; m_ViewStartY
= 0;
66 m_PopupMenu
= MakeFormatMenu();
67 m_memDC
= new wxMemoryDC
;
68 m_bitmap
= new wxBitmap(4,4);
69 m_bitmapSize
= wxPoint(4,4);
70 m_llist
= new wxLayoutList();
71 wxPoint max
= m_llist
->GetSize();
72 SetScrollbars(10, 20 /*lineHeight*/, max
.x
/10+1, max
.y
/20+1);
73 EnableScrolling(true,true);
74 m_maxx
= max
.x
; m_maxy
= max
.y
;
78 wxLayoutWindow::~wxLayoutWindow()
80 delete m_memDC
; // deletes bitmap automatically (?)
88 wxLayoutWindow::MSWGetDlgCode()
90 // if we don't return this, we won't get OnChar() events for TABs and ENTER
91 return DLGC_WANTCHARS
| DLGC_WANTARROWS
| DLGC_WANTMESSAGE
;
96 wxLayoutWindow::OnMouse(int eventId
, wxMouseEvent
& event
)
98 if(!m_doSendEvents
) // nothing to do
101 wxPaintDC
dc( this );
106 findPos
.x
= dc
.DeviceToLogicalX(event
.GetX());
107 findPos
.y
= dc
.DeviceToLogicalY(event
.GetY());
109 #ifdef WXLAYOUT_DEBUG
110 wxLogDebug("wxLayoutWindow::OnMouse: (%d, %d) -> (%d, %d)",
111 event
.GetX(), event
.GetY(), findPos
.x
, findPos
.y
);
114 m_ClickPosition
= findPos
;
115 wxLayoutObject
*obj
= m_llist
->FindObject(findPos
);
117 #ifdef WXLAYOUT_DEBUG
119 wxLogDebug("wxLayoutWindow::OnMouse: Found object of type %d.",
122 wxLogDebug("wxLayoutWindow::OnMouse: Found no object.");
125 // only do the menu if activated, editable and not on a clickable object
126 if(eventId
== WXLOWIN_MENU_RCLICK
128 && (! obj
|| (obj
&& obj
->GetUserData() == NULL
))
131 PopupMenu(m_PopupMenu
, event
.GetX(), event
.GetY());
134 // find the object at this position
137 wxCommandEvent
commandEvent(wxEVT_COMMAND_MENU_SELECTED
, eventId
);
138 commandEvent
.SetEventObject( this );
139 commandEvent
.SetClientData((char *)obj
);
140 GetEventHandler()->ProcessEvent(commandEvent
);
145 * Some simple keyboard handling.
148 wxLayoutWindow::OnChar(wxKeyEvent
& event
)
150 if(!IsEditable()) // do nothing
156 long keyCode
= event
.KeyCode();
158 /* First, handle control keys */
159 if(event
.ControlDown() && ! event
.AltDown())
161 switch(event
.KeyCode())
168 m_llist
->DeleteLines(1);
170 case 'h': // like backspace
171 if(m_llist
->MoveCursorHorizontally(-1)) m_llist
->Delete(1);
174 m_llist
->DeleteToBeginOfLine();
177 m_llist
->DeleteToEndOfLine();
184 else if( event
.AltDown() && ! event
.ControlDown() )
186 switch(event
.KeyCode())
190 m_llist
->DeleteWord();
197 else if ( ! event
.AltDown() && ! event
.ControlDown())
199 switch(event
.KeyCode())
202 m_llist
->MoveCursorHorizontally(1);
205 m_llist
->MoveCursorHorizontally(-1);
208 m_llist
->MoveCursorVertically(-1);
211 m_llist
->MoveCursorVertically(1);
214 m_llist
->MoveCursorVertically(-20);
217 m_llist
->MoveCursorVertically(20);
220 m_llist
->MoveCursorToBeginOfLine();
223 m_llist
->MoveCursorToEndOfLine();
228 case WXK_BACK
: // backspace
229 if(m_llist
->MoveCursorHorizontally(-1)) m_llist
->Delete(1);
232 m_llist
->LineBreak();
235 if((!(event
.ControlDown() || event
.AltDown() || event
.MetaDown()))
236 && (keyCode
< 256 && keyCode
>= 32)
241 m_llist
->Insert(tmp
);
242 //// m_llist->WrapLine();
248 DoPaint(true); // paint and scroll to cursor
252 wxLayoutWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
)) // or: OnDraw(wxDC& dc)
258 wxLayoutWindow::DoPaint(bool scrollToCursor
)
260 wxPaintDC
dc( this );
263 int x0
,y0
,x1
,y1
, dx
, dy
;
265 // Calculate where the top of the visible area is:
267 GetScrollPixelsPerUnit(&dx
, &dy
);
270 // Get the size of the visible window:
271 GetClientSize(&x1
,&y1
);
276 // Maybe we need to change the scrollbar sizes or positions,
277 // so layout the list and check:
278 if(IsDirty() || scrollToCursor
)
283 /* Make sure that the scrollbars are at a position so that the
284 cursor is visible if we are editing. */
285 /** Scroll so that cursor is visible! */
286 if(IsEditable() && scrollToCursor
)
288 wxPoint cc
= m_llist
->GetCursorScreenPos();
289 if(cc
.x
< x0
|| cc
.y
< y0
290 || cc
.x
>= x0
+(9*x1
)/10 || cc
.y
>= y0
+(9*y1
/10)) // (9*x)/10 == 90%
293 nx
= cc
.x
- x1
/2; if(nx
< 0) nx
= 0;
294 ny
= cc
.y
- y1
/2; if(ny
< 0) ny
= 0;
295 Scroll(nx
/dx
,ny
/dy
); // new view start
300 /* Check whether the window has grown, if so, we need to reallocate
301 the bitmap to be larger. */
302 if(x1
> m_bitmapSize
.x
|| y1
> m_bitmapSize
.y
)
304 wxASSERT(m_bitmapSize
.x
> 0);
305 wxASSERT(m_bitmapSize
.y
> 0);
307 m_memDC
->SelectObject(wxNullBitmap
);
309 m_bitmapSize
= wxPoint(x1
,y1
);
310 m_bitmap
= new wxBitmap(x1
,y1
);
311 m_memDC
->SelectObject(*m_bitmap
);
313 // Device origins on the memDC are suspect, we translate manually
314 // with the translate parameter of Draw().
315 m_memDC
->SetDeviceOrigin(0,0);
318 // The +4 give the window a tiny border on the left and top, looks nice.
319 wxPoint
offset(-x0
+4,-y0
+4);
320 m_llist
->Draw(*m_memDC
,offset
);
322 m_llist
->DrawCursor(*m_memDC
,m_HaveFocus
,offset
);
323 // Now copy everything to the screen:
324 dc
.Blit(x0
,y0
,x1
,y1
,m_memDC
,0,0,wxCOPY
,FALSE
);
330 // change the range and position of scroll bars
332 wxLayoutWindow::ResizeScrollbars(bool exact
)
334 wxPoint max
= m_llist
->GetSize();
336 if(max
.x
> m_maxx
|| max
.y
> m_maxy
337 || max
.x
< (7*m_maxx
)/10 || max
.y
<< (7*m_maxy
)/10
340 if(! exact
) // add an extra 20% to the sizes to avoid future updates
342 max
.x
= (12*max
.x
)/10; // 12/20 = 120%
343 max
.y
= (12*max
.y
)/10;
345 ViewStart(&m_ViewStartX
, &m_ViewStartY
);
346 SetScrollbars(10, 20, max
.x
/10+1,max
.y
/20+1,m_ViewStartX
,m_ViewStartY
,true);
347 m_maxx
= max
.x
; m_maxy
= max
.y
;
353 wxLayoutWindow::MakeFormatMenu()
355 wxMenu
*m
= new wxMenu(_("Layout Menu"));
357 m
->Append(WXLOWIN_MENU_LARGER
,_("&Larger"),_("Switch to larger font."), false);
358 m
->Append(WXLOWIN_MENU_SMALLER
,_("&Smaller"),_("Switch to smaller font."), false);
359 m
->AppendSeparator();
360 m
->Append(WXLOWIN_MENU_UNDERLINE_ON
, _("&Underline on"),_("Activate underline mode."), false);
361 m
->Append(WXLOWIN_MENU_UNDERLINE_OFF
,_("&Underline off"),_("Deactivate underline mode."), false);
362 m
->Append(WXLOWIN_MENU_BOLD_ON
,_("&Bold on"),_("Activate bold mode."), false);
363 m
->Append(WXLOWIN_MENU_BOLD_OFF
,_("&Bold off"),_("Deactivate bold mode."), false);
364 m
->Append(WXLOWIN_MENU_ITALICS_ON
,_("&Italics on"),_("Activate italics mode."), false);
365 m
->Append(WXLOWIN_MENU_ITALICS_OFF
,_("&Italics off"),_("Deactivate italics mode."), false);
366 m
->AppendSeparator();
367 m
->Append(WXLOWIN_MENU_ROMAN
,_("&Roman"),_("Switch to roman font."), false);
368 m
->Append(WXLOWIN_MENU_TYPEWRITER
,_("&Typewriter"),_("Switch to typewriter font."), false);
369 m
->Append(WXLOWIN_MENU_SANSSERIF
,_("&Sans Serif"),_("Switch to sans serif font."), false);
373 void wxLayoutWindow::OnMenu(wxCommandEvent
& event
)
375 switch (event
.GetId())
377 case WXLOWIN_MENU_LARGER
:
378 m_llist
->SetFontLarger(); break;
379 case WXLOWIN_MENU_SMALLER
:
380 m_llist
->SetFontSmaller(); break;
381 case WXLOWIN_MENU_UNDERLINE_ON
:
382 m_llist
->SetFontUnderline(true); break;
383 case WXLOWIN_MENU_UNDERLINE_OFF
:
384 m_llist
->SetFontUnderline(false); break;
385 case WXLOWIN_MENU_BOLD_ON
:
386 m_llist
->SetFontWeight(wxBOLD
); break;
387 case WXLOWIN_MENU_BOLD_OFF
:
388 m_llist
->SetFontWeight(wxNORMAL
); break;
389 case WXLOWIN_MENU_ITALICS_ON
:
390 m_llist
->SetFontStyle(wxITALIC
); break;
391 case WXLOWIN_MENU_ITALICS_OFF
:
392 m_llist
->SetFontStyle(wxNORMAL
); break;
393 case WXLOWIN_MENU_ROMAN
:
394 m_llist
->SetFontFamily(wxROMAN
); break;
395 case WXLOWIN_MENU_TYPEWRITER
:
396 m_llist
->SetFontFamily(wxFIXED
); break;
397 case WXLOWIN_MENU_SANSSERIF
:
398 m_llist
->SetFontFamily(wxSWISS
); break;
403 wxLayoutWindow::OnSetFocus(wxFocusEvent
&ev
)
406 DoPaint(); // to repaint the cursor
410 wxLayoutWindow::OnKillFocus(wxFocusEvent
&ev
)
413 DoPaint(); // to repaint the cursor