1 /*-*- c++ -*-********************************************************
2 * wxFTCanvas: a canvas for editing formatted text *
4 * (C) 1998 by Karsten Ballüder (Ballueder@usa.net) *
7 *******************************************************************/
10 - each Object knows its size and how to draw itself
11 - the list is responsible for calculating positions
12 - the draw coordinates for each object are the top left corner
13 - coordinates only get calculated when things get redrawn
14 - during redraw each line gets iterated over twice, first just
15 calculating baselines and positions, second to actually draw it
16 - the cursor position is the position before an object, i.e. if the
17 buffer starts with a text-object, cursor 0,0 is just before the
20 - the cursor position and size must be decided at layout/draw time
21 or the fonts will be wrong
26 - MaxX()/MaxY() don't get set
31 #pragma implementation "wxllist.h"
36 # include "gui/wxllist.h"
42 # include "iostream.h"
44 # include <wx/postscrp.h>
45 # include <wx/print.h>
49 #define BASELINESTRETCH 12
52 static const char *g_aTypeStrings
[] =
54 "invalid", "text", "cmd", "icon", "linebreak"
57 # define wxLayoutDebug wxLogDebug
58 # define WXL_VAR(x) cerr << #x " = " << x << endl;
59 # define WXL_DBG_POINT(p) wxLogDebug(#p ": (%d, %d)", p.x, p.y)
60 # define WXL_TRACE(f) wxLogDebug(#f ": ")
61 # define TypeString(t) g_aTypeStrings[t]
64 wxLayoutObjectBase::Debug(void)
67 wxLogDebug("%s: size = %dx%d, bl = %d",
68 TypeString(GetType()), GetSize(&bl
).x
, GetSize(&bl
).y
, bl
);
73 # define WXL_DBG_POINT(p)
75 # define ShowCurrentObject()
76 # define TypeString(t) ""
77 inline void wxLayoutDebug(const char *, ...) { }
81 //-------------------------- wxLayoutObjectText
83 wxLayoutObjectText::wxLayoutObjectText(const String
&txt
)
88 m_Position
= wxPoint(-1,-1);
93 wxLayoutObjectText::GetSize(CoordType
*baseLine
) const
95 if(baseLine
) *baseLine
= m_BaseLine
;
96 return wxPoint(m_Width
, m_Height
);
100 wxLayoutObjectText::Draw(wxDC
&dc
, wxPoint
const &translate
)
102 dc
.DrawText(Str(m_Text
), m_Position
.x
+ translate
.x
, m_Position
.y
+translate
.y
);
108 wxLayoutObjectText::Layout(wxDC
&dc
, wxPoint position
, CoordType baseLine
)
112 if(m_Position
.x
!= position
.x
|| m_Position
.y
!= position
.y
)
115 m_Position
= position
;
116 dc
.GetTextExtent(Str(m_Text
),&m_Width
, &m_Height
, &descent
);
117 m_BaseLine
= m_Height
- descent
;
118 if(m_Position
.x
!= position
.x
|| m_Position
.y
!= position
.y
)
122 #ifdef WXLAYOUT_DEBUG
124 wxLayoutObjectText::Debug(void)
126 wxLayoutObjectBase::Debug();
127 wxLogDebug(" `%s`", m_Text
.c_str());
131 //-------------------------- wxLayoutObjectIcon
133 wxLayoutObjectIcon::wxLayoutObjectIcon(wxIcon
const &icon
)
135 m_Position
= wxPoint(-1,-1);
136 m_Icon
= new wxIcon(icon
);
139 wxLayoutObjectIcon::wxLayoutObjectIcon(wxIcon
*icon
)
145 wxLayoutObjectIcon::Draw(wxDC
&dc
, wxPoint
const &translate
)
147 dc
.DrawIcon(m_Icon
,m_Position
.x
+translate
.x
, m_Position
.y
+translate
.y
);
151 wxLayoutObjectIcon::Layout(wxDC
&dc
, wxPoint position
, CoordType baseLine
)
153 if(m_Position
.x
!= position
.x
|| m_Position
.y
!= position
.y
)
155 m_Position
= position
;
159 wxLayoutObjectIcon::GetSize(CoordType
*baseLine
) const
161 if(baseLine
) *baseLine
= m_Icon
->GetHeight();
162 return wxPoint(m_Icon
->GetWidth(), m_Icon
->GetHeight());
165 //-------------------------- wxLayoutObjectCmd
168 wxLayoutObjectCmd::wxLayoutObjectCmd(int size
, int family
, int style
, int
169 weight
, bool underline
,
170 wxColour
const *fg
, wxColour
const *bg
)
173 m_font
= new wxFont(size
,family
,style
,weight
,underline
);
178 wxLayoutObjectCmd::~wxLayoutObjectCmd()
184 wxLayoutObjectCmd::GetStyle(void) const
186 wxLayoutStyleInfo
*si
= new wxLayoutStyleInfo();
189 si
->size
= m_font
->GetPointSize();
190 si
->family
= m_font
->GetFamily();
191 si
->style
= m_font
->GetStyle();
192 si
->underline
= m_font
->GetUnderlined();
193 si
->weight
= m_font
->GetWeight();
195 si
->fg_red
= m_ColourFG
->Red();
196 si
->fg_green
= m_ColourFG
->Green();
197 si
->fg_blue
= m_ColourFG
->Blue();
198 si
->bg_red
= m_ColourBG
->Red();
199 si
->bg_green
= m_ColourBG
->Green();
200 si
->bg_blue
= m_ColourBG
->Blue();
206 wxLayoutObjectCmd::Draw(wxDC
&dc
, wxPoint
const &translate
)
211 dc
.SetTextForeground(*m_ColourFG
);
213 dc
.SetTextBackground(*m_ColourBG
);
216 wxLayoutObjectCmd::Layout(wxDC
&dc
, wxPoint p
, CoordType baseline
)
218 m_Position
= p
; // required so we can find the right object for cursor
219 // this get called, so that recalculation uses right font sizes
220 Draw(dc
,wxPoint(0,0));
223 //-------------------------- wxLayoutList
225 wxLayoutList::wxLayoutList()
227 m_DefaultSetting
= NULL
;
231 wxLayoutList::~wxLayoutList()
234 delete m_DefaultSetting
;
235 // no deletion of objects, they are owned by the list
239 wxLayoutList::LineBreak(void)
241 Insert(new wxLayoutObjectLineBreak
);
242 m_CursorPosition
.x
= 0; m_CursorPosition
.y
++;
246 wxLayoutList::SetFont(int family
, int size
, int style
, int weight
,
247 int underline
, wxColour
const *fg
,
250 if(family
!= -1) m_FontFamily
= family
;
251 if(size
!= -1) m_FontPtSize
= size
;
252 if(style
!= -1) m_FontStyle
= style
;
253 if(weight
!= -1) m_FontWeight
= weight
;
254 if(underline
!= -1) m_FontUnderline
= underline
!= 0;
256 if(fg
!= NULL
) m_ColourFG
= fg
;
257 if(bg
!= NULL
) m_ColourBG
= bg
;
260 new wxLayoutObjectCmd(m_FontPtSize
,m_FontFamily
,m_FontStyle
,m_FontWeight
,m_FontUnderline
,
261 m_ColourFG
, m_ColourBG
));
265 wxLayoutList::SetFont(int family
, int size
, int style
, int weight
,
266 int underline
, char const *fg
, char const *bg
)
274 cfg
= wxTheColourDatabase
->FindColour(fg
);
276 cbg
= wxTheColourDatabase
->FindColour(bg
);
278 SetFont(family
,size
,style
,weight
,underline
,cfg
,cbg
);
282 /// for access by wxLayoutWindow:
284 wxLayoutList::GetSize(CoordType
*max_x
, CoordType
*max_y
,
285 CoordType
*lineHeight
)
288 if(max_x
) *max_x
= m_MaxX
;
289 if(max_y
) *max_y
= m_MaxY
;
290 if(lineHeight
) *lineHeight
= m_LineHeight
;
294 wxLayoutList::ResetSettings(wxDC
&dc
)
296 // setting up the default:
297 dc
.SetTextForeground( *wxBLACK
);
298 dc
.SetTextBackground( *wxWHITE
);
299 dc
.SetBackgroundMode( wxSOLID
); // to enable setting of text background
300 dc
.SetFont( *wxNORMAL_FONT
);
302 m_DefaultSetting
->Draw(dc
,wxPoint(0,0));
306 wxLayoutList::Layout(wxDC
&dc
, wxLayoutMargins
*margins
)
310 // first object in current line
311 wxLayoutObjectList::iterator headOfLine
;
312 // where we draw next
313 wxPoint position
, position_HeadOfLine
;
314 // size of last object
316 CoordType baseLine
= m_FontPtSize
;
317 CoordType baseLineSkip
= (BASELINESTRETCH
* baseLine
)/10;
318 CoordType objBaseLine
= baseLine
;
319 wxLayoutObjectType type
;
321 // we need to count cursor positions
322 wxPoint cursorPos
= wxPoint(0,0);
324 wxLayoutObjectBase
*cursorObject
= NULL
; // let's find it again
328 position
.y
= margins
->top
;
329 position
.x
= margins
->left
;
341 position_HeadOfLine
= position
;
348 type
= (*i
)->GetType();
349 (*i
)->Layout(dc
, position
, baseLine
);
350 size
= (*i
)->GetSize(&objBaseLine
);
351 // calculate next object's position:
352 position
.x
+= size
.x
;
354 // do we need to increase the line's height?
355 if(size
.y
> baseLineSkip
)
357 baseLineSkip
= size
.y
;
358 i
= headOfLine
; position
= position_HeadOfLine
;
361 if(objBaseLine
> baseLine
)
363 baseLine
= objBaseLine
;
364 i
= headOfLine
; position
= position_HeadOfLine
;
368 // when we reach here, the coordinates are valid, this part of
369 // the loop gets run only once per object
370 if(position
.x
> m_MaxX
)
372 if(type
== WXLO_TYPE_LINEBREAK
)
374 cursorPos
.x
= 0; cursorPos
.y
++;
377 cursorPos
.x
+= (**i
).CountPositions();
379 // now check whether we have finished handling this line:
380 if(type
== WXLO_TYPE_LINEBREAK
&& i
!= tail())
382 position
.x
= margins
? margins
->left
: 0;
383 position
.y
+= baseLineSkip
;
384 baseLine
= m_FontPtSize
;
385 objBaseLine
= baseLine
; // not all objects set it
386 baseLineSkip
= (BASELINESTRETCH
* baseLine
)/10;
389 position_HeadOfLine
= position
;
391 if(cursorObject
== NULL
&& cursorPos
.y
== m_CursorPosition
.y
) // look for cursor
393 if(cursorPos
.x
>= m_CursorPosition
.x
&&
394 m_CursorPosition
.x
-cursorPos
.x
+(**i
).CountPositions()) // cursor is in current object
403 m_MaxY
= position
.y
+ baseLineSkip
;
407 wxLayoutList::Draw(wxDC
&dc
,
408 CoordType fromLine
, CoordType toLine
,
410 wxPoint
const &translate
)
412 Layout(dc
); // FIXME just for now
416 wxLayoutObjectList::iterator i
;
418 if(start
== iterator(NULL
))
420 else // we need to restore font settings
422 for( i
= begin() ; i
!= start
; i
++)
423 if((**i
).GetType() == WXLO_TYPE_CMD
)
424 (**i
).Draw(dc
,translate
); // apply font settings
427 while( start
!= end() && (**start
).GetPosition().y
< fromLine
)
429 if((**start
).GetType() == WXLO_TYPE_CMD
)
430 (**start
).Draw(dc
,translate
); // apply font settings
434 i
!= end() && (toLine
== -1 || (**i
).GetPosition().y
< toLine
) ;
436 (*i
)->Draw(dc
,translate
);
439 /** Erase at least to end of line */
441 wxLayoutList::EraseAndDraw(wxDC
&dc
, iterator start
)
443 //look for begin of line
444 while(start
!= end() && start
!= begin() && (**start
).GetType() !=
447 if(start
== iterator(NULL
))
449 if(start
== iterator(NULL
))
452 wxPoint p
= (**start
).GetPosition();
454 WXL_VAR(p
.x
);WXL_VAR(p
.y
);
455 //FIXME: wxGTK: MaxX()/MaxY() broken
456 //WXL_VAR(dc.MaxX()); WXL_VAR(dc.MaxY());
457 dc
.SetBrush(*wxWHITE_BRUSH
);
458 dc
.SetPen(wxPen(*wxWHITE
,0,wxTRANSPARENT
));
459 dc
.DrawRectangle(p
.x
,p
.y
,2000,2000); //dc.MaxX(),dc.MaxY());
460 Draw(dc
,-1,-1,start
,wxPoint(0,0));
461 //dc.DrawRectangle(p.x,p.y,2000,2000); //dc.MaxX(),dc.MaxY());
466 wxLayoutList::CalculateCursor(wxDC
&dc
)
468 CoordType width
, height
, descent
;
469 CoordType baseLineSkip
= 20; //FIXME
472 wxLayoutObjectBase
&obj
= **FindCurrentObject(&offset
);
475 DrawCursor(dc
,true); // erase it
476 m_CursorCoords
= obj
.GetPosition();
477 WXL_VAR(m_CursorCoords
.x
);
478 if(obj
.GetType() == WXLO_TYPE_TEXT
)
480 wxLayoutObjectText
*tobj
= (wxLayoutObjectText
*)&obj
;
481 String
& str
= tobj
->GetText();
482 String sstr
= str
.substr(0,offset
);
484 dc
.GetTextExtent(sstr
,&width
,&height
,&descent
);
486 m_CursorCoords
= wxPoint(m_CursorCoords
.x
+width
,
488 m_CursorSize
= wxPoint(2,height
);
490 else if(obj
.GetType() == WXLO_TYPE_LINEBREAK
)
492 m_CursorCoords
= wxPoint(0, m_CursorCoords
.y
);
493 m_CursorSize
= wxPoint(2,baseLineSkip
);
497 // this is not necessarily the most "beautiful" solution:
498 //cursorPosition = wxPoint(position.x, position.y);
499 //cursorSize = wxPoint(size.x > 0 ? size.x : 1,size.y > 0 ? size.y : baseLineSkip);
500 m_CursorCoords
= wxPoint(m_CursorCoords
.x
+obj
.GetSize().x
, m_CursorCoords
.y
);
501 m_CursorSize
= wxPoint(2, obj
.GetSize().y
);
502 if(m_CursorSize
.y
< 1) m_CursorSize
.y
= baseLineSkip
;
504 WXL_VAR(m_CursorCoords
.x
);
505 m_CursorMoved
= false; // coords are valid
509 wxLayoutList::DrawCursor(wxDC
&dc
, bool erase
)
514 //dc.SetBrush(*wxWHITE_BRUSH);
515 //dc.SetPen(wxPen(*wxWHITE,1,wxSOLID));
516 //dc.DrawRectangle(m_CursorCoords.x, m_CursorCoords.y, m_CursorSize.x, m_CursorSize.y);
517 dc
.Blit(m_CursorCoords
.x
, m_CursorCoords
.y
, m_CursorSize
.x
,
518 m_CursorSize
.y
, &m_CursorMemDC
,
523 if(IsDirty() || CursorMoved())
529 wxBitmap
bm(m_CursorSize
.x
,m_CursorSize
.y
);
530 m_CursorMemDC
.SelectObject(bm
);
531 m_CursorMemDC
.Blit(0, 0, m_CursorSize
.x
, m_CursorSize
.y
,
532 &dc
, m_CursorCoords
.x
,
533 m_CursorCoords
.y
, 0, 0);
534 dc
.SetBrush(*wxBLACK_BRUSH
);
535 dc
.SetPen(wxPen(*wxBLACK
,1,wxSOLID
));
536 dc
.DrawRectangle(m_CursorCoords
.x
, m_CursorCoords
.y
,
537 m_CursorSize
.x
, m_CursorSize
.y
);
547 #ifdef WXLAYOUT_DEBUG
549 wxLayoutList::Debug(void)
552 wxLayoutObjectList::iterator i
;
554 wxLogDebug("------------------------debug start-------------------------");
555 for(i
= begin(); i
!= end(); i
++)
557 wxLogDebug("-----------------------debug end----------------------------");
559 // show current object:
561 i
= FindCurrentObject(&offs
);
562 wxLogDebug(" line length: %l", (long int) GetLineLength(i
,offs
));
565 wxLogDebug("<<no object found>>");
566 return; // FIXME we should set cursor position to maximum allowed
569 if((*i
)->GetType() == WXLO_TYPE_TEXT
)
570 wxLogDebug(" \"%s\", offs=%d",((wxLayoutObjectText
*)(*i
))->GetText().c_str(), (int) offs
);
572 wxLogDebug(g_aTypeStrings
[(*i
)->GetType()]);
577 wxLayoutList::ShowCurrentObject()
580 wxLayoutObjectList::iterator i
= FindCurrentObject(&offs
);
582 wxLayoutDebug("Cursor is at (%d, %d)",
583 m_CursorPosition
.x
, m_CursorPosition
.y
);
585 i
= FindCurrentObject(&offs
);
586 wxLogDebug(" Line length: %d", GetLineLength(i
));
590 wxLogDebug("<<no object found>>");
591 return; // FIXME we should set cursor position to maximum allowed
594 if((*i
)->GetType() == WXLO_TYPE_TEXT
)
595 wxLogDebug(" \"%s\", offs: %d",
596 ((wxLayoutObjectText
*)(*i
))->GetText().c_str(), offs
);
598 wxLogDebug(" %s", TypeString((*i
)->GetType()));
603 /******************** editing stuff ********************/
605 // don't change this, I know how to optimise this and will do it real
610 * Finds the object belonging to a given cursor position cpos and
611 * returns an iterator to that object and stores the relative cursor
612 * position in offset.
614 * For linebreaks, the offset can be 0=before or 1=after.
616 * If the cpos coordinates don't exist, they are modified.
619 wxLayoutObjectList::iterator
620 wxLayoutList::FindObjectCursor(wxPoint
*cpos
, CoordType
*offset
)
622 wxPoint object
= wxPoint(0,0); // runs along the objects
624 wxLayoutObjectList::iterator i
, begin_it
;
627 //#ifdef WXLAYOUT_DEBUG
628 // wxLayoutDebug("Looking for object at (%d, %d)", cpos->x, cpos->y);
631 // optimisation: compare to last looked at object:
632 if(cpos
->y
> m_FoundCursor
.y
|| (cpos
->y
== m_FoundCursor
.y
&&
633 cpos
->x
>= m_FoundCursor
.x
))
638 //broken at the moment
639 //begin_it = m_FoundIterator;
640 //m_FoundCursor = *cpos;
643 for(i
= begin_it
; i
!= end() && object
.y
<= cpos
->y
; )
645 width
= (**i
).CountPositions();
646 if(cpos
->y
== object
.y
) // a possible candidate
648 if((**i
).GetType() ==WXLO_TYPE_LINEBREAK
)
650 if(cpos
->x
== object
.x
)
652 if(offset
) *offset
= 0;
653 return m_FoundIterator
= i
;
655 if(offset
) *offset
=1;
657 return m_FoundIterator
= i
;
659 if(cpos
->x
>= object
.x
&& cpos
->x
<= object
.x
+width
) // overlap
661 if(offset
) *offset
= cpos
->x
-object
.x
;
662 //#ifdef WXLAYOUT_DEBUG
663 // wxLayoutDebug(" found object at (%d, %d), type: %s",
664 // object.x, object.y, TypeString((*i)->GetType()));
666 return m_FoundIterator
= i
;
669 // no overlap, increment coordinates
671 if((**i
).GetType() == WXLO_TYPE_LINEBREAK
)
681 //#ifdef WXLAYOUT_DEBUG
682 // wxLayoutDebug(" not found");
684 // return last object, coordinates of that one:
687 return m_FoundIterator
= i
;
688 if((**i
).GetType()==WXLO_TYPE_LINEBREAK
)
692 return m_FoundIterator
= i
;
694 cpos
->x
= object
.x
; // would be the coordinate of next object
696 cpos
->x
+= width
; // last object's width
697 if(*offset
) *offset
= cpos
->x
-object
.x
;
698 return m_FoundIterator
= i
; // not found
701 wxLayoutObjectList::iterator
702 wxLayoutList::FindCurrentObject(CoordType
*offset
)
704 wxLayoutObjectList::iterator obj
= end();
706 obj
= FindObjectCursor(&m_CursorPosition
, offset
);
707 if(obj
== end()) // not ideal yet
710 if(obj
!= end()) // tail really exists
711 *offset
= (*obj
)->CountPositions(); // at the end of it
717 wxLayoutList::MoveCursor(int dx
, int dy
)
719 CoordType offs
, lineLength
;
720 wxLayoutObjectList::iterator i
;
722 m_CursorMoved
= true;
724 bool rc
= true; // have we moved?
726 if(dy
> 0 && m_CursorPosition
.y
< m_MaxLine
)
727 m_CursorPosition
.y
+= dy
;
728 else if(dy
< 0 && m_CursorPosition
.y
> 0)
729 m_CursorPosition
.y
+= dy
; // dy is negative
730 if(m_CursorPosition
.y
< 0)
732 m_CursorPosition
.y
= 0;
735 else if (m_CursorPosition
.y
> m_MaxLine
)
737 m_CursorPosition
.y
= m_MaxLine
;
743 i
= FindCurrentObject(&offs
);
744 lineLength
= GetLineLength(i
,offs
);
745 if(m_CursorPosition
.x
< lineLength
)
747 m_CursorPosition
.x
++;
753 if(m_CursorPosition
.y
< m_MaxLine
)
755 m_CursorPosition
.y
++;
756 m_CursorPosition
.x
= 0;
762 break; // cannot move there
768 if(m_CursorPosition
.x
> 0)
770 m_CursorPosition
.x
--;
775 if(m_CursorPosition
.y
> 0)
777 m_CursorPosition
.y
--;
778 m_CursorPosition
.x
= 0;
779 i
= FindCurrentObject(&offs
);
780 lineLength
= GetLineLength(i
,offs
);
781 m_CursorPosition
.x
= lineLength
;
788 break; // cannot move left any more
793 i
= FindCurrentObject(&offs
);
794 lineLength
= GetLineLength(i
,offs
);
795 if(m_CursorPosition
.x
> lineLength
)
797 m_CursorPosition
.x
= lineLength
;
800 #ifdef WXLAYOUT_DEBUG
807 wxLayoutList::Delete(CoordType count
)
819 wxLayoutObjectList::iterator i
;
823 i
= FindCurrentObject(&offs
);
824 startover
: // ugly, but easiest way to do it
826 return; // we cannot delete anything more
828 /* Here we need to treat linebreaks differently.
829 If offs==0 we are before the linebreak, otherwise behind. */
830 if((*i
)->GetType() == WXLO_TYPE_LINEBREAK
)
837 continue; // we're done
839 else // delete the object behind the linebreak
841 i
++; // we increment and continue as normal
846 else if((*i
)->GetType() == WXLO_TYPE_TEXT
)
848 wxLayoutObjectText
*tobj
= (wxLayoutObjectText
*)*i
;
849 CoordType len
= tobj
->CountPositions();
850 // If we find the end of a text object, this means that we
851 // have to delete from the object following it.
858 else if(len
<= count
) // delete this object
867 tobj
->GetText().erase(offs
,len
);
868 return; // we are done
871 else// all other objects: delete the object
872 // this only works as expected if the non-text object has 0/1
873 // as offset values. Not tested with "longer" objects.
875 CoordType len
= (*i
)->CountPositions();
878 count
= count
> len
? count
-= len
: 0;
879 erase(i
); // after this, i is the iterator for the following object
882 else // delete the following object
884 i
++; // we increment and continue as normal
890 while(count
&& i
!= end());
894 wxLayoutList::Insert(wxLayoutObjectBase
*obj
)
896 wxCHECK_RET( obj
, "no object to insert" );
901 wxLayoutObjectList::iterator i
= FindCurrentObject(&offs
);
903 // WXL_TRACE(Insert(obj));
909 // do we have to split a text object?
910 else if((*i
)->GetType() == WXLO_TYPE_TEXT
&& offs
!= (*i
)->CountPositions())
912 wxLayoutObjectText
*tobj
= (wxLayoutObjectText
*) *i
;
913 #ifdef WXLAYOUT_DEBUG
914 wxLayoutDebug("text: %s", tobj
->GetText().c_str());
917 String left
= tobj
->GetText().substr(0,offs
); // get part before cursor
918 WXL_VAR(left
.c_str());
919 tobj
->GetText() = tobj
->GetText().substr(offs
,(*i
)->CountPositions()-offs
); // keeps the right half
920 WXL_VAR(tobj
->GetText().c_str());
922 insert(i
,new wxLayoutObjectText(left
)); // inserts before
926 // all other cases, append after object:
927 wxLayoutObjectList::iterator j
= i
; // we want to apend after this object
935 m_CursorPosition
.x
+= obj
->CountPositions();
936 if(obj
->GetType() == WXLO_TYPE_LINEBREAK
)
938 m_CursorMoved
= true;
942 wxLayoutList::Insert(String
const &text
)
944 wxLayoutObjectText
*tobj
= NULL
;
945 wxLayoutObjectList::iterator j
;
947 // WXL_TRACE(Insert(text));
955 wxLayoutObjectList::iterator i
= FindCurrentObject(&offs
);
959 Insert(new wxLayoutObjectText(text
));
963 switch((**i
).GetType())
966 // insert into an existing text object:
967 WXL_TRACE(inserting into existing object
);
968 tobj
= (wxLayoutObjectText
*)*i
;
970 tobj
->GetText().insert(offs
,text
);
972 case WXLO_TYPE_LINEBREAK
:
975 if(offs
== 0) // try to append to previous object
978 if(j
!= end() && (**j
).GetType() == WXLO_TYPE_TEXT
)
980 tobj
= (wxLayoutObjectText
*)*j
;
981 tobj
->GetText()+=text
;
984 insert(i
,new wxLayoutObjectText(text
));
986 else // cursor after linebreak
989 if(j
!= end() && (**j
).GetType() == WXLO_TYPE_TEXT
)
991 tobj
= (wxLayoutObjectText
*)*j
;
992 tobj
->GetText()=text
+tobj
->GetText();
997 push_back(new wxLayoutObjectText(text
));
999 insert(j
,new wxLayoutObjectText(text
));
1004 m_CursorPosition
.x
+= strlen(text
.c_str());
1005 m_CursorMoved
= true;
1009 wxLayoutList::GetLineLength(wxLayoutObjectList::iterator i
, CoordType offs
)
1016 if(offs
== 0 && (**i
).GetType() == WXLO_TYPE_LINEBREAK
)
1017 // we are before a linebrak
1019 // search backwards for beginning of line:
1020 while(i
!= begin() && (*i
)->GetType() != WXLO_TYPE_LINEBREAK
)
1022 if((*i
)->GetType() == WXLO_TYPE_LINEBREAK
)
1024 // now we can start counting:
1025 while(i
!= end() && (*i
)->GetType() != WXLO_TYPE_LINEBREAK
)
1027 len
+= (*i
)->CountPositions();
1034 wxLayoutList::Clear(int family
, int size
, int style
, int weight
,
1035 int underline
, char const *fg
, char const *bg
)
1038 m_CursorMoved
= true;
1039 m_dirty
= true; // force redraw/recalc
1040 wxLayoutObjectList::iterator i
= begin();
1043 m_CursorMemDC
.SelectObject(bm
);
1045 while(i
!= end()) // == while valid
1049 m_FontPtSize
= size
;
1050 m_FontUnderline
= false;
1051 m_FontFamily
= family
;
1052 m_FontStyle
= style
;
1053 m_FontWeight
= weight
;
1054 m_ColourFG
= wxTheColourDatabase
->FindColour(fg
);
1055 m_ColourBG
= wxTheColourDatabase
->FindColour(bg
);
1057 if(! m_ColourFG
) m_ColourFG
= wxBLACK
;
1058 if(! m_ColourBG
) m_ColourBG
= wxWHITE
;
1060 m_Position
= wxPoint(0,0);
1061 m_CursorPosition
= wxPoint(0,0);
1063 m_LineHeight
= (BASELINESTRETCH
*m_FontPtSize
)/10;
1064 m_MaxX
= 0; m_MaxY
= 0;
1067 m_FoundCursor
= wxPoint(0,0);
1068 m_FoundIterator
= begin();
1070 if(m_DefaultSetting
)
1071 delete m_DefaultSetting
;
1073 m_DefaultSetting
= new
1074 wxLayoutObjectCmd(m_FontPtSize
,m_FontFamily
,m_FontStyle
,
1075 m_FontWeight
,m_FontUnderline
,
1076 m_ColourFG
, m_ColourBG
);
1080 wxLayoutObjectBase
*
1081 wxLayoutList::Find(wxPoint coords
) const
1083 wxLayoutObjectList::iterator i
= begin();
1085 wxPoint topleft
, bottomright
;
1087 while(i
!= end()) // == while valid
1089 wxLayoutObjectBase
*object
= *i
;
1090 topleft
= object
->GetPosition();
1091 if(coords
.y
>= topleft
.y
&& coords
.x
>= topleft
.x
)
1093 bottomright
= topleft
;
1094 bottomright
.x
+= object
->GetSize().x
;
1095 bottomright
.y
+= object
->GetSize().y
;
1096 if(coords
.x
<= bottomright
.x
&& coords
.y
<= bottomright
.y
)
1105 /******************** printing stuff ********************/
1107 bool wxLayoutPrintout::OnPrintPage(int page
)
1113 top
= (page
- 1)*m_PageHeight
;
1114 bottom
= top
+ m_PageHeight
;
1115 // SetDeviceOrigin() doesn't work here, so we need to manually
1116 // translate all coordinates.
1117 wxPoint
translate(0,-top
);
1118 m_llist
->Draw(*dc
,top
,bottom
,wxLayoutObjectList::iterator(NULL
),translate
);
1125 bool wxLayoutPrintout::OnBeginDocument(int startPage
, int endPage
)
1127 if (!wxPrintout::OnBeginDocument(startPage
, endPage
))
1134 wxLayoutPrintout::OnPreparePrinting(void)
1140 void wxLayoutPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *selPageFrom
, int *selPageTo
)
1142 // ugly hack to get number of pages
1143 wxPostScriptDC
psdc("tmp.ps",false);
1144 psdc
.GetSize(&m_PageWidth
, &m_PageHeight
); // that's all we need it for
1146 m_Margins
.top
= m_PageHeight
/ 10; // 10%
1147 m_Margins
.bottom
= m_PageHeight
- m_PageHeight
/ 10; // 90%
1148 m_Margins
.left
= m_PageWidth
/ 10;
1149 m_Margins
.right
= m_PageWidth
- m_PageWidth
/ 10;
1151 m_PageHeight
= m_Margins
.bottom
- m_Margins
.top
- m_Margins
.bottom
;
1152 m_PageWidth
= m_Margins
.right
- m_Margins
.left
- m_Margins
.right
;
1154 m_NumOfPages
= (int)( m_llist
->GetSize().y
/ (float)(m_PageHeight
) + 0.5);
1156 *maxPage
= m_NumOfPages
-1;
1159 *selPageTo
= m_NumOfPages
-1;
1163 bool wxLayoutPrintout::HasPage(int pageNum
)
1165 return pageNum
< m_NumOfPages
;
1170 wxLayoutList::MakePrintout(wxString
const &name
)
1172 return new wxLayoutPrintout(*this,name
);