MSW fixes for wxLayout, part II: now breaking and merging line works too.

Scrolling still doesn't :-(


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2662 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
1999-06-03 22:36:01 +00:00
parent 239bca2e6d
commit bcf4a975e4
6 changed files with 270 additions and 160 deletions

View File

@@ -38,7 +38,7 @@ IMPLEMENT_APP(MyApp)
ID_PRINT_SETUP_PS, ID_PAGE_SETUP_PS,ID_PREVIEW_PS, ID_PRINT_SETUP_PS, ID_PAGE_SETUP_PS,ID_PREVIEW_PS,
ID_WRAP, ID_NOWRAP, ID_PASTE, ID_COPY, ID_CUT, ID_FIND, ID_WRAP, ID_NOWRAP, ID_PASTE, ID_COPY, ID_CUT, ID_FIND,
ID_WXLAYOUT_DEBUG, ID_QUIT, ID_CLICK, ID_HTML, ID_TEXT, ID_WXLAYOUT_DEBUG, ID_QUIT, ID_CLICK, ID_HTML, ID_TEXT,
ID_TEST, ID_LONG_TEST }; ID_TEST, ID_LINEBREAKS_TEST, ID_LONG_TEST, ID_URL_TEST };
IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame ) IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
@@ -59,7 +59,8 @@ IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
MyFrame::MyFrame(void) : MyFrame::MyFrame(void) :
wxFrame( (wxFrame *) NULL, -1, (char *) "wxLayout", wxPoint(20,20), wxSize(600,360) ) wxFrame( (wxFrame *) NULL, -1, "wxLayout",
wxPoint(880,100), wxSize(256,256) )
{ {
CreateStatusBar( 2 ); CreateStatusBar( 2 );
@@ -80,24 +81,27 @@ MyFrame::MyFrame(void) :
file_menu->Append(ID_PREVIEW_PS, "Print Preview PostScript", "Preview (PostScript)"); file_menu->Append(ID_PREVIEW_PS, "Print Preview PostScript", "Preview (PostScript)");
#endif #endif
file_menu->AppendSeparator(); file_menu->AppendSeparator();
file_menu->Append( ID_TEXT, "Export Text"); file_menu->Append( ID_TEXT, "Export &Text");
file_menu->Append( ID_HTML, "Export HTML"); file_menu->Append( ID_HTML, "Export &HTML");
file_menu->Append( ID_QUIT, "Exit"); file_menu->Append( ID_QUIT, "E&xit");
menu_bar->Append(file_menu, "File" ); menu_bar->Append(file_menu, "&File" );
wxMenu *edit_menu = new wxMenu; wxMenu *edit_menu = new wxMenu;
edit_menu->Append( ID_CLEAR, "Clear"); edit_menu->Append( ID_CLEAR, "C&lear");
edit_menu->Append( ID_ADD_SAMPLE, "Example"); edit_menu->Append( ID_ADD_SAMPLE, "&Example");
edit_menu->Append( ID_LONG_TEST, "Add many lines"); edit_menu->Append( ID_LONG_TEST, "Add &many lines");
edit_menu->AppendSeparator(); edit_menu->AppendSeparator();
edit_menu->Append(ID_WRAP, "Wrap mode", "Activate wrapping at pixel 200."); edit_menu->Append( ID_LINEBREAKS_TEST, "Add &several lines");
edit_menu->Append(ID_NOWRAP, "No-wrap mode", "Deactivate wrapping."); edit_menu->Append( ID_URL_TEST, "Insert an &URL");
edit_menu->AppendSeparator(); edit_menu->AppendSeparator();
edit_menu->Append(ID_COPY, "Copy", "Copy text to clipboard."); edit_menu->Append(ID_WRAP, "&Wrap mode", "Activate wrapping at pixel 200.");
edit_menu->Append(ID_CUT, "Cut", "Cut text to clipboard."); edit_menu->Append(ID_NOWRAP, "&No-wrap mode", "Deactivate wrapping.");
edit_menu->Append(ID_PASTE,"Paste", "Paste text from clipboard."); edit_menu->AppendSeparator();
edit_menu->Append(ID_FIND, "Find", "Find text."); edit_menu->Append(ID_COPY, "&Copy", "Copy text to clipboard.");
menu_bar->Append(edit_menu, "Edit" ); edit_menu->Append(ID_CUT, "Cu&t", "Cut text to clipboard.");
edit_menu->Append(ID_PASTE,"&Paste", "Paste text from clipboard.");
edit_menu->Append(ID_FIND, "&Find", "Find text.");
menu_bar->Append(edit_menu, "&Edit" );
#ifndef __WXMSW__ #ifndef __WXMSW__
menu_bar->Show( TRUE ); menu_bar->Show( TRUE );
@@ -191,8 +195,7 @@ MyFrame::AddSampleText(wxLayoutList *llist)
fgets(buffer,1024,in); fgets(buffer,1024,in);
if(feof(in)) if(feof(in))
break; break;
llist->Insert(buffer); wxLayoutImportText(llist, buffer);
llist->LineBreak();
} }
} }
llist->MoveCursorTo(wxPoint(0,0)); llist->MoveCursorTo(wxPoint(0,0));
@@ -300,6 +303,19 @@ void MyFrame::OnCommand( wxCommandEvent &event )
m_lwin->Refresh(); m_lwin->Refresh();
break; break;
} }
case ID_LINEBREAKS_TEST:
wxLayoutImportText(m_lwin->GetLayoutList(),
"This is a text\n"
"with embedded line\n"
"breaks.\n");
break;
case ID_URL_TEST:
// VZ: this doesn't work, of course, but I think it should -
// wxLayoutWindow should have a flag m_highlightUrls and do it itself
// (instead of doing it manually like M does now)
m_lwin->GetLayoutList()->Insert("http://www.wxwindows.org/");
} }
}; };

View File

@@ -75,7 +75,7 @@
// waste time looking for it right now. Search for occurences of // waste time looking for it right now. Search for occurences of
// MSW_CORRECTION to find all the places where I did it. // MSW_CORRECTION to find all the places where I did it.
#ifdef __WXMSW__ #ifdef __WXMSW__
static const int MSW_CORRECTION = 10; static const int MSW_CORRECTION = 5;
#else #else
static const int MSW_CORRECTION = 0; static const int MSW_CORRECTION = 0;
#endif #endif
@@ -278,10 +278,16 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
{ {
long descent = 0l; long descent = 0l;
// now this is done in wxLayoutLine::Layout(), but this code might be
// reenabled later - in principle, it's more efficient
#if 0
CoordType widthOld = m_Width, CoordType widthOld = m_Width,
heightOld = m_Height; heightOld = m_Height;
#endif // 0
dc.GetTextExtent(m_Text, &m_Width, &m_Height, &descent); dc.GetTextExtent(m_Text, &m_Width, &m_Height, &descent);
#if 0
if ( widthOld != m_Width || heightOld != m_Height ) if ( widthOld != m_Width || heightOld != m_Height )
{ {
// as the text length changed, it must be refreshed // as the text length changed, it must be refreshed
@@ -302,6 +308,7 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
llist->SetUpdateRect(position.x + widthOld + MSW_CORRECTION, llist->SetUpdateRect(position.x + widthOld + MSW_CORRECTION,
position.y + heightOld + MSW_CORRECTION); position.y + heightOld + MSW_CORRECTION);
} }
#endif // 0
m_Bottom = descent; m_Bottom = descent;
m_Top = m_Height - m_Bottom; m_Top = m_Height - m_Bottom;
@@ -582,7 +589,7 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
m_LineNumber = 0; m_LineNumber = 0;
m_Width = m_Height = 0; m_Width = m_Height = 0;
m_Length = 0; m_Length = 0;
m_Dirty = true; MarkDirty(0);
m_Previous = prev; m_Previous = prev;
m_Next = NULL; m_Next = NULL;
RecalculatePosition(llist); RecalculatePosition(llist);
@@ -610,6 +617,8 @@ wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
{ {
wxASSERT(m_Previous || GetLineNumber() == 0); wxASSERT(m_Previous || GetLineNumber() == 0);
wxPoint posOld(m_Position);
if(m_Previous) if(m_Previous)
{ {
m_Position = m_Previous->GetPosition(); m_Position = m_Previous->GetPosition();
@@ -617,7 +626,18 @@ wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
} }
else else
m_Position = wxPoint(0,0); m_Position = wxPoint(0,0);
llist->SetUpdateRect(m_Position);
if ( m_Position != posOld )
{
// the whole line moved and must be repainted
llist->SetUpdateRect(m_Position);
llist->SetUpdateRect(m_Position.x + GetWidth() + MSW_CORRECTION,
m_Position.y + GetHeight() + MSW_CORRECTION);
llist->SetUpdateRect(posOld);
llist->SetUpdateRect(posOld.x + GetWidth() + MSW_CORRECTION,
posOld.y + GetHeight() + MSW_CORRECTION);
}
return m_Position; return m_Position;
} }
@@ -740,11 +760,8 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
wxASSERT(xpos >= 0); wxASSERT(xpos >= 0);
wxASSERT(obj != NULL); wxASSERT(obj != NULL);
// in any case, the object is going to belong to this line MarkDirty(xpos);
obj->AttachToLine(this);
//FIXME: this could be optimised, for now be prudent:
m_Dirty = true;
CoordType offset; CoordType offset;
wxLOiterator i = FindObject(xpos, &offset); wxLOiterator i = FindObject(xpos, &offset);
if(i == NULLIT) if(i == NULLIT)
@@ -796,11 +813,12 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
} }
bool bool
wxLayoutLine::Insert(CoordType xpos, wxString text) wxLayoutLine::Insert(CoordType xpos, const wxString& text)
{ {
wxASSERT(xpos >= 0); wxASSERT(xpos >= 0);
//FIXME: this could be optimised, for now be prudent:
m_Dirty = true; MarkDirty(xpos);
CoordType offset; CoordType offset;
wxLOiterator i = FindObject(xpos, &offset); wxLOiterator i = FindObject(xpos, &offset);
if(i != NULLIT && (**i).GetType() == WXLO_TYPE_TEXT) if(i != NULLIT && (**i).GetType() == WXLO_TYPE_TEXT)
@@ -808,11 +826,14 @@ wxLayoutLine::Insert(CoordType xpos, wxString text)
wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i; wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i;
tobj->GetText().insert(offset, text); tobj->GetText().insert(offset, text);
m_Length += text.Length(); m_Length += text.Length();
return true;
} }
else else
return Insert(xpos, new wxLayoutObjectText(text)); {
if ( !Insert(xpos, new wxLayoutObjectText(text)) )
return false;
}
return true;
} }
CoordType CoordType
@@ -822,8 +843,7 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos)
wxASSERT(xpos >= 0); wxASSERT(xpos >= 0);
wxASSERT(npos >= 0); wxASSERT(npos >= 0);
//FIXME: this could be optimised, for now be prudent: MarkDirty(xpos);
m_Dirty = true;
wxLOiterator i = FindObject(xpos, &offset); wxLOiterator i = FindObject(xpos, &offset);
while(npos > 0) while(npos > 0)
{ {
@@ -878,8 +898,7 @@ wxLayoutLine::DeleteWord(CoordType xpos)
{ {
wxASSERT(xpos >= 0); wxASSERT(xpos >= 0);
CoordType offset; CoordType offset;
//FIXME: this could be optimised, for now be prudent: MarkDirty(xpos);
m_Dirty = true;
wxLOiterator i = FindObject(xpos, &offset); wxLOiterator i = FindObject(xpos, &offset);
@@ -984,23 +1003,29 @@ wxLayoutLine::Layout(wxDC &dc,
{ {
wxLayoutObjectList::iterator i; wxLayoutObjectList::iterator i;
// when a line becomes dirty, we redraw it from the place where it was
// changed till the end of line (because the following wxLayoutObjects are
// moved when the preceding one changes) - calculate the update rectangle.
CoordType updateTop = m_Position.y,
updateLeft = -1,
updateWidth = m_Width,
updateHeight = m_Height;
CoordType CoordType
oldWidth = m_Width, topHeight = 0,
oldHeight = m_Height; bottomHeight = 0; // above and below baseline
CoordType CoordType
topHeight, bottomHeight; // above and below baseline objTopHeight, objBottomHeight; // above and below baseline
CoordType
objHeight = 0,
objTopHeight, objBottomHeight;
CoordType CoordType
len, count = 0; len, count = 0;
m_Height = 0; m_BaseLine = 0;
m_Width = 0;
topHeight = 0; bottomHeight = 0;
wxPoint size;
bool cursorFound = false;
m_Dirty = false; CoordType heightOld = m_Height;
m_Height = 0;
m_Width = 0;
m_BaseLine = 0;
bool cursorFound = false;
if(cursorPos) if(cursorPos)
{ {
@@ -1013,15 +1038,17 @@ wxLayoutLine::Layout(wxDC &dc,
//llist->ApplyStyle(&m_StyleInfo, dc); //llist->ApplyStyle(&m_StyleInfo, dc);
for(i = m_ObjectList.begin(); i != NULLIT; i++) for(i = m_ObjectList.begin(); i != NULLIT; i++)
{ {
(**i).Layout(dc, llist); wxLayoutObject *obj = *i;
size = (**i).GetSize(&objTopHeight, &objBottomHeight); obj->Layout(dc, llist);
wxPoint sizeObj = obj->GetSize(&objTopHeight, &objBottomHeight);
if(cursorPos && ! cursorFound) if(cursorPos && ! cursorFound)
{ // we need to check whether the text cursor is here {
len = (**i).GetLength(); // we need to check whether the text cursor is here
len = obj->GetLength();
if(count <= cx && count+len > cx) if(count <= cx && count+len > cx)
{ {
if((**i).GetType() == WXLO_TYPE_TEXT) if(obj->GetType() == WXLO_TYPE_TEXT)
{ {
len = cx - count; // pos in object len = cx - count; // pos in object
CoordType width, height, descent; CoordType width, height, descent;
@@ -1030,7 +1057,7 @@ wxLayoutLine::Layout(wxDC &dc,
cursorPos->x += width; cursorPos->x += width;
cursorPos->y = m_Position.y; cursorPos->y = m_Position.y;
wxString str; wxString str;
if(len < (**i).GetLength()) if(len < obj->GetLength())
str = (*(wxLayoutObjectText*)*i).GetText().substr(len,1); str = (*(wxLayoutObjectText*)*i).GetText().substr(len,1);
else else
str = WXLO_CURSORCHAR; str = WXLO_CURSORCHAR;
@@ -1038,15 +1065,16 @@ wxLayoutLine::Layout(wxDC &dc,
wxASSERT(cursorSize); wxASSERT(cursorSize);
// Just in case some joker inserted an empty string object: // Just in case some joker inserted an empty string object:
if(width == 0) width = WXLO_MINIMUM_CURSOR_WIDTH; if(width == 0) width = WXLO_MINIMUM_CURSOR_WIDTH;
if(height == 0) height = objHeight; if(height == 0) height = sizeObj.y;
cursorSize->x = width; cursorSize->x = width;
cursorSize->y = height; cursorSize->y = height;
cursorFound = true; // no more checks cursorFound = true; // no more checks
} }
else else
{ // on some other object {
// on some other object
CoordType top, bottom; // unused CoordType top, bottom; // unused
*cursorSize = (**i).GetSize(&top,&bottom); *cursorSize = obj->GetSize(&top,&bottom);
cursorPos->y = m_Position.y; cursorPos->y = m_Position.y;
cursorFound = true; // no more checks cursorFound = true; // no more checks
} }
@@ -1054,28 +1082,43 @@ wxLayoutLine::Layout(wxDC &dc,
else else
{ {
count += len; count += len;
cursorPos->x += (**i).GetWidth(); cursorPos->x += obj->GetWidth();
} }
} // cursor finding } // cursor finding
objHeight = size.y;
m_Width += size.x; m_Width += sizeObj.x;
if(objHeight > m_Height) m_Height = objHeight; if(sizeObj.y > m_Height)
if(objTopHeight > topHeight) topHeight = objTopHeight; {
if(objBottomHeight > bottomHeight) bottomHeight = objBottomHeight; m_Height = sizeObj.y;
}
if(objTopHeight > topHeight)
topHeight = objTopHeight;
if(objBottomHeight > bottomHeight)
bottomHeight = objBottomHeight;
} }
// special case of a line which becomes empty (after deletion, for example): if ( IsDirty() )
// we should invalidate the screen space it occupied (usually this happens
// from wxLayoutObject::Layout called in the loop above)
if ( m_ObjectList.empty() )
{ {
wxPoint position(GetPosition()); if ( updateHeight < m_Height )
llist->SetUpdateRect(position.x + oldWidth + MSW_CORRECTION, updateHeight = m_Height;
position.y + oldHeight + MSW_CORRECTION); if ( updateWidth < m_Width )
updateWidth = m_Width;
// update all line if we don't know where to start from
if ( updateLeft == -1 )
updateLeft = 0;
llist->SetUpdateRect(updateLeft, updateTop);
llist->SetUpdateRect(updateLeft + updateWidth + MSW_CORRECTION,
updateTop + updateHeight + MSW_CORRECTION);
} }
if(topHeight + bottomHeight > m_Height) if(topHeight + bottomHeight > m_Height)
{
m_Height = topHeight+bottomHeight; m_Height = topHeight+bottomHeight;
}
m_BaseLine = topHeight; m_BaseLine = topHeight;
if(m_Height == 0) if(m_Height == 0)
@@ -1086,10 +1129,12 @@ wxLayoutLine::Layout(wxDC &dc,
m_BaseLine = m_Height - descent; m_BaseLine = m_Height - descent;
} }
// tell next line about coordinate change // tell next line about coordinate change
if(m_Next && objHeight != oldHeight) if(m_Next && m_Height != heightOld)
{
// FIXME isn't this done in RecalculatePositions() below anyhow?
m_Next->RecalculatePositions(0, llist); m_Next->RecalculatePositions(0, llist);
}
// We need to check whether we found a valid cursor size: // We need to check whether we found a valid cursor size:
if(cursorPos) if(cursorPos)
@@ -1106,7 +1151,10 @@ wxLayoutLine::Layout(wxDC &dc,
if(m_BaseLine >= cursorSize->y) // the normal case anyway if(m_BaseLine >= cursorSize->y) // the normal case anyway
cursorPos->y += m_BaseLine-cursorSize->y; cursorPos->y += m_BaseLine-cursorSize->y;
} }
RecalculatePositions(1, llist); RecalculatePositions(1, llist);
MarkClean();
} }
@@ -1114,8 +1162,8 @@ wxLayoutLine *
wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist) wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
{ {
wxASSERT(xpos >= 0); wxASSERT(xpos >= 0);
//FIXME: this could be optimised, for now be prudent:
m_Dirty = true; MarkDirty(xpos);
/* If we are at the begin of a line, we want to move all other /* If we are at the begin of a line, we want to move all other
lines down and stay with the cursor where we are. However, if we lines down and stay with the cursor where we are. However, if we
@@ -1157,13 +1205,17 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
i++; // don't move this object to the new list i++; // don't move this object to the new list
} }
else else
{
if(offset > 0) if(offset > 0)
i++; // move objects from here to new list i++; // move objects from here to new list
}
while(i != m_ObjectList.end()) while(i != m_ObjectList.end())
{ {
newLine->Append(*i); wxLayoutObject *obj = *i;
m_Length -= (**i).GetLength(); newLine->Append(obj);
m_Length -= obj->GetLength();
m_ObjectList.remove(i); // remove without deleting it m_ObjectList.remove(i); // remove without deleting it
} }
if(m_Next) if(m_Next)
@@ -1178,8 +1230,8 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
wxCHECK_RET(GetNextLine(),"wxLayout internal error: no next line to merge"); wxCHECK_RET(GetNextLine(),"wxLayout internal error: no next line to merge");
wxLayoutObjectList &list = GetNextLine()->m_ObjectList; wxLayoutObjectList &list = GetNextLine()->m_ObjectList;
wxLOiterator i; wxLOiterator i;
//FIXME: this could be optimised, for now be prudent:
m_Dirty = true; MarkDirty(GetWidth());
wxLayoutObject *last = NULL; wxLayoutObject *last = NULL;
for(i = list.begin(); i != list.end();) for(i = list.begin(); i != list.end();)
@@ -1200,7 +1252,6 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
else else
{ {
// just append the object "as was" // just append the object "as was"
current->UnattachFromLine();
Append(current); Append(current);
list.remove(i); // remove without deleting it list.remove(i); // remove without deleting it
@@ -1211,13 +1262,24 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
wxLayoutLine *oldnext = GetNextLine(); wxLayoutLine *oldnext = GetNextLine();
wxLayoutLine *nextLine = oldnext->GetNextLine(); wxLayoutLine *nextLine = oldnext->GetNextLine();
SetNext(nextLine); SetNext(nextLine);
delete oldnext;
if ( nextLine ) if ( nextLine )
{ {
nextLine->MoveLines(-1); nextLine->MoveLines(-1);
} }
else
{
// this is now done in Delete(), but if this function is ever called
// from elsewhere, we might have to move refresh code back here (in
// order not to duplicate it)
#if 0
wxPoint pos(oldnext->GetPosition());
llist->SetUpdateRect(pos);
llist->SetUpdateRect(pos.x + oldnext->GetWidth() + MSW_CORRECTION,
pos.y + oldnext->GetHeight() + MSW_CORRECTION);
#endif // 0
}
// no RecalculatePositions needed - called from Delete() anyhow delete oldnext;
} }
CoordType CoordType
@@ -1613,12 +1675,20 @@ bool
wxLayoutList::Insert(wxString const &text) wxLayoutList::Insert(wxString const &text)
{ {
wxASSERT(m_CursorLine); wxASSERT(m_CursorLine);
wxASSERT_MSG( text.Find('\n') == wxNOT_FOUND, "use wxLayoutImportText!" );
if ( !text )
return true;
AddCursorPosToUpdateRect(); AddCursorPosToUpdateRect();
m_CursorLine->Insert(m_CursorPos.x, text); if ( !m_CursorLine->Insert(m_CursorPos.x, text) )
return false;
m_CursorPos.x += text.Length(); m_CursorPos.x += text.Length();
m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
m_CursorLine->RecalculatePositions(0, this);
return true; return true;
} }
@@ -1634,7 +1704,9 @@ wxLayoutList::Insert(wxLayoutObject *obj)
m_CursorLine->Insert(m_CursorPos.x, obj); m_CursorLine->Insert(m_CursorPos.x, obj);
m_CursorPos.x += obj->GetLength(); m_CursorPos.x += obj->GetLength();
m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
m_CursorLine->RecalculatePositions(0, this);
return true; return true;
} }
@@ -1710,7 +1782,9 @@ wxLayoutList::WrapLine(CoordType column)
LineBreak(); LineBreak();
Delete(1); // delete the space Delete(1); // delete the space
m_CursorPos.x = newpos; m_CursorPos.x = newpos;
m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
m_CursorLine->RecalculatePositions(1, this);
return true; return true;
} }
} }
@@ -1762,9 +1836,19 @@ wxLayoutList::Delete(CoordType npos)
wasMerged = true; wasMerged = true;
wxLayoutLine *next = m_CursorLine->GetNextLine(); wxLayoutLine *next = m_CursorLine->GetNextLine();
if ( next ) if ( next )
{
totalHeight += next->GetHeight(); totalHeight += next->GetHeight();
m_CursorLine->MergeNextLine(this); totalWidth += next->GetWidth();
left--;
m_CursorLine->MergeNextLine(this);
left--;
}
else
{
wxFAIL_MSG("can't delete all this");
return false;
}
} }
} }
} }
@@ -1776,6 +1860,7 @@ wxLayoutList::Delete(CoordType npos)
if ( wasMerged ) if ( wasMerged )
{ {
wxPoint position(m_CursorLine->GetPosition()); wxPoint position(m_CursorLine->GetPosition());
SetUpdateRect(position);
SetUpdateRect(position.x + totalWidth + MSW_CORRECTION, SetUpdateRect(position.x + totalWidth + MSW_CORRECTION,
position.y + totalHeight + MSW_CORRECTION); position.y + totalHeight + MSW_CORRECTION);
} }
@@ -1850,11 +1935,13 @@ wxLayoutList::GetCursorScreenPos(wxDC &dc)
void void
wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll) wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll)
{ {
wxLayoutLine *line = m_FirstLine;
// first, make sure everything is calculated - this might not be // first, make sure everything is calculated - this might not be
// needed, optimise it later // needed, optimise it later
ApplyStyle(&m_DefaultSetting, dc); ApplyStyle(&m_DefaultSetting, dc);
// FIXME this is completely wrong - we should start by first *visible* line
// (and stop on the last one) instead of looping over all lines!!
wxLayoutLine *line = m_FirstLine;
while(line) while(line)
{ {
if(forceAll || line->IsDirty()) if(forceAll || line->IsDirty())
@@ -1865,10 +1952,13 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll)
(wxPoint *)&m_CursorSize, m_CursorPos.x); (wxPoint *)&m_CursorSize, m_CursorPos.x);
else else
line->Layout(dc, this); line->Layout(dc, this);
// little condition to speed up redrawing:
if(bottom != -1 && line->GetPosition().y > bottom) break; // little condition to speed up redrawing:
if(bottom != -1 && line->GetPosition().y > bottom)
break;
} }
line->RecalculatePositions(1,this);
line->RecalculatePositions(1, this);
line = line->GetNextLine(); line = line->GetNextLine();
} }
@@ -1924,14 +2014,22 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos,
wxLayoutLine *line = m_FirstLine; wxLayoutLine *line = m_FirstLine;
wxPoint p; wxPoint p;
// we need to run a layout here to get font sizes right :-(
ApplyStyle(&m_DefaultSetting, dc); ApplyStyle(&m_DefaultSetting, dc);
while(line) while(line)
{ {
p = line->GetPosition(); p = line->GetPosition();
if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y) if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y)
break; break;
#if 0
// we need to run a layout here to get font sizes right :-(
// VZ: we can't call Layout() from here because it marks the line as
// clean and it is not refreshed when it's called from wxLayoutList::
// Layout() - if we really need to do this, we should introduce an
// extra argument to Layout() to prevent the line from MarkClean()ing
// itself here
line->Layout(dc, this); line->Layout(dc, this);
#endif
line = line->GetNextLine(); line = line->GetNextLine();
} }
if(line == NULL) if(line == NULL)

View File

@@ -162,7 +162,7 @@ public:
virtual CoordType GetOffsetScreen(wxDC &dc, CoordType xpos) const { return 0; } virtual CoordType GetOffsetScreen(wxDC &dc, CoordType xpos) const { return 0; }
/// constructor /// constructor
wxLayoutObject() { m_UserData = NULL; m_Line = NULL; } wxLayoutObject() { m_UserData = NULL; }
/// delete the user data /// delete the user data
virtual ~wxLayoutObject() { if(m_UserData) m_UserData->DecRef(); } virtual ~wxLayoutObject() { if(m_UserData) m_UserData->DecRef(); }
@@ -183,20 +183,6 @@ public:
m_UserData->IncRef(); m_UserData->IncRef();
} }
/// returns the line we belong to (or NULL)
wxLayoutLine *GetLine() const { return m_Line; }
/// attaches this object to the given line, it's an error to reattach us
void AttachToLine(wxLayoutLine *line)
{
wxASSERT_MSG( !m_Line, "this layout object already belongs to a line" );
m_Line = line;
}
/// unattaches the object (should reattach it immediately afterwards!)
void UnattachFromLine() { if ( m_Line ) m_Line = (wxLayoutLine *)NULL; }
/** Return the user data. /** Return the user data.
Increments the object's reference count. When no longer needed, Increments the object's reference count. When no longer needed,
caller must call DecRef() on the pointer returned. caller must call DecRef() on the pointer returned.
@@ -221,9 +207,6 @@ public:
protected: protected:
/// optional data for application's use /// optional data for application's use
UserData *m_UserData; UserData *m_UserData;
/// the line of the text we belong to or NULL if we're not shown on screen
wxLayoutLine *m_Line;
}; };
/// Define a list type of wxLayoutObject pointers. /// Define a list type of wxLayoutObject pointers.
@@ -472,7 +455,7 @@ public:
@param text the text to insert @param text the text to insert
@return true if that xpos existed and the object was inserted @return true if that xpos existed and the object was inserted
*/ */
bool Insert(CoordType xpos, wxString text); bool Insert(CoordType xpos, const wxString& text);
/** This function appends an object to the line. /** This function appends an object to the line.
@param obj the object to insert @param obj the object to insert
@@ -481,7 +464,6 @@ public:
{ {
wxASSERT(obj); wxASSERT(obj);
obj->AttachToLine(this);
m_ObjectList.push_back(obj); m_ObjectList.push_back(obj);
m_Length += obj->GetLength(); m_Length += obj->GetLength();
} }
@@ -665,7 +647,19 @@ public:
/// Returns dirty state /// Returns dirty state
bool IsDirty(void) const { return m_Dirty; } bool IsDirty(void) const { return m_Dirty; }
/// Marks line as diry. /// Marks line as diry.
void MarkDirty(void) { m_Dirty = true; } void MarkDirty(CoordType left = -1)
{
if ( left != -1 )
{
if ( m_updateLeft == -1 || left < m_updateLeft )
m_updateLeft = left;
}
m_Dirty = true;
}
/// Reset the dirty flag
void MarkClean() { m_Dirty = false; m_updateLeft = -1; }
private: private:
/// Destructor is private. Use DeleteLine() to remove it. /// Destructor is private. Use DeleteLine() to remove it.
~wxLayoutLine(); ~wxLayoutLine();
@@ -706,6 +700,8 @@ private:
wxLayoutObjectList m_ObjectList; wxLayoutObjectList m_ObjectList;
/// Have we been changed since the last layout? /// Have we been changed since the last layout?
bool m_Dirty; bool m_Dirty;
/// The coordinate of the left boundary of the update rectangle (if m_Dirty)
CoordType m_updateLeft;
/// Pointer to previous line if it exists. /// Pointer to previous line if it exists.
wxLayoutLine *m_Previous; wxLayoutLine *m_Previous;
/// Pointer to next line if it exists. /// Pointer to next line if it exists.

View File

@@ -28,29 +28,30 @@
#define BASE_SIZE 12 #define BASE_SIZE 12
inline static bool IsEndOfLine(const char *p, int mode) inline static bool IsEndOfLine(const char *p)
{ {
// in addition to Unix EOL convention we also (but not instead) understand // the end of line is either just '\n' or "\r\n" - we understand both (even
// the DOS one under Windows // though the second is used only under DOS/Windows) to be able to import
return // DOS text files even under Unix
(mode == WXLO_EXPORT_WITH_CRLF) ? return (*p == '\n') || ((*p == '\r') && (*(p + 1) == '\n'));
((*p == '\r') && (*(p + 1) == '\n'))
:
(((*p == '\r') && (*(p + 1) == '\n'))||(*p == '\n'));
} }
void wxLayoutImportText(wxLayoutList *list, wxString const &str, int withflag) void wxLayoutImportText(wxLayoutList *list, wxString const &str)
{ {
if(str.Length() == 0) if ( !str )
return; return;
char * cptr = (char *)str.c_str(); // string gets changed only temporarily
// we change the string temporarily inside this function
wxString& s = (wxString &)str; // const_cast
char * cptr = s.GetWriteBuf(s.Len());
const char * begin = cptr; const char * begin = cptr;
char backup; char backup;
for(;;) for(;;)
{ {
begin = cptr; begin = cptr;
while( *cptr && !IsEndOfLine(cptr, withflag) ) while( *cptr && !IsEndOfLine(cptr) )
cptr++; cptr++;
backup = *cptr; backup = *cptr;
*cptr = '\0'; *cptr = '\0';
@@ -58,7 +59,7 @@ void wxLayoutImportText(wxLayoutList *list, wxString const &str, int withflag)
*cptr = backup; *cptr = backup;
// check if it's the end of this line // check if it's the end of this line
if ( IsEndOfLine(cptr, withflag) ) if ( IsEndOfLine(cptr) )
{ {
// if it was "\r\n", skip the following '\n' // if it was "\r\n", skip the following '\n'
if ( *cptr == '\r' ) if ( *cptr == '\r' )
@@ -69,6 +70,8 @@ void wxLayoutImportText(wxLayoutList *list, wxString const &str, int withflag)
break; break;
cptr++; cptr++;
} }
s.UngetWriteBuf();
} }
static static

View File

@@ -62,24 +62,17 @@ struct wxLayoutExportStatus
}; };
#ifdef OS_WIN #ifdef OS_WIN
/// import text into a wxLayoutList (including linefeeds): #define WXLO_DEFAULT_EXPORT_MODE WXLO_EXPORT_WITH_CRLF
void wxLayoutImportText(wxLayoutList *list, wxString const &str, #else // Unix
int withflag = WXLO_EXPORT_WITH_CRLF); #define WXLO_DEFAULT_EXPORT_MODE WXLO_EXPORT_WITH_LF_ONLY
#endif // Win/Unix
wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status,
int mode = WXLO_EXPORT_AS_TEXT,
int flags =
WXLO_EXPORT_WITH_CRLF);
#else
/// import text into a wxLayoutList (including linefeeds): /// import text into a wxLayoutList (including linefeeds):
void wxLayoutImportText(wxLayoutList *list, wxString const &str, void wxLayoutImportText(wxLayoutList *list, wxString const &str);
int withflag = WXLO_EXPORT_WITH_LF_ONLY);
/// export text in a given format /// export text in a given format
wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status, wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status,
int mode = WXLO_EXPORT_AS_TEXT, int mode = WXLO_EXPORT_AS_TEXT,
int flags = int flags = WXLO_DEFAULT_EXPORT_MODE);
WXLO_EXPORT_WITH_LF_ONLY);
#endif
#endif //WXLPARSER_H #endif //WXLPARSER_H

View File

@@ -28,10 +28,7 @@
# include "gui/wxlparser.h" # include "gui/wxlparser.h"
#else #else
# ifdef __WXMSW__ # ifdef __WXMSW__
# include <windows.h> # include <wx/msw/private.h>
# undef FindWindow
# undef GetCharWidth
# undef StartDoc
# endif # endif
# include "wxlwindow.h" # include "wxlwindow.h"
@@ -153,9 +150,13 @@ wxLayoutWindow::MSWGetDlgCode()
void void
wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
{ {
wxPaintDC dc( this ); wxClientDC dc( this );
PrepareDC( dc ); PrepareDC( dc );
SetFocus(); if ( eventId != WXLOWIN_MENU_MOUSEMOVE )
{
// moving the mouse in a window shouldn't give it the focus!
SetFocus();
}
wxPoint findPos; wxPoint findPos;
findPos.x = dc.DeviceToLogicalX(event.GetX()); findPos.x = dc.DeviceToLogicalX(event.GetX());
@@ -512,10 +513,13 @@ wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)) // or: OnDraw(wxDC& dc)
void void
wxLayoutWindow::DoPaint(const wxRect *updateRect) wxLayoutWindow::DoPaint(const wxRect *updateRect)
{ {
#ifdef __WXGTK__ #ifndef __WXMSW__
InternalPaint(updateRect); InternalPaint(updateRect);
#else #else
Refresh(FALSE, updateRect); // Causes bad flicker under wxGTK!!! Refresh(FALSE, updateRect); // Causes bad flicker under wxGTK!!!
if ( !::UpdateWindow(GetHwnd()) )
wxLogLastError("UpdateWindow");
#endif #endif
} }
@@ -876,12 +880,12 @@ void
wxLayoutWindow::OnSetFocus(wxFocusEvent &ev) wxLayoutWindow::OnSetFocus(wxFocusEvent &ev)
{ {
m_HaveFocus = true; m_HaveFocus = true;
//FIXME: need argument DoPaint(); // to repaint the cursor ev.Skip();
} }
void void
wxLayoutWindow::OnKillFocus(wxFocusEvent &ev) wxLayoutWindow::OnKillFocus(wxFocusEvent &ev)
{ {
m_HaveFocus = false; m_HaveFocus = false;
//FIXME: need argument DoPaint(); // to repaint the cursor ev.Skip();
} }