Update OpenVMS compile support
[wxWidgets.git] / src / html / m_list.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/html/m_list.cpp
3 // Purpose: wxHtml module for lists
4 // Author: Vaclav Slavik
5 // RCS-ID: $Id$
6 // Copyright: (c) 1999 Vaclav Slavik
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #include "wx/wxprec.h"
11
12 #ifdef __BORLANDC__
13 #pragma hdrstop
14 #endif
15
16 #if wxUSE_HTML && wxUSE_STREAMS
17
18 #ifndef WX_PRECOMP
19 #include "wx/brush.h"
20 #include "wx/dc.h"
21 #endif
22
23 #include "wx/html/forcelnk.h"
24 #include "wx/html/m_templ.h"
25
26 #include "wx/html/htmlcell.h"
27
28 FORCE_LINK_ME(m_list)
29
30
31 //-----------------------------------------------------------------------------
32 // wxHtmlListmarkCell
33 //-----------------------------------------------------------------------------
34
35 class wxHtmlListmarkCell : public wxHtmlCell
36 {
37 private:
38 wxBrush m_Brush;
39 public:
40 wxHtmlListmarkCell(wxDC *dc, const wxColour& clr);
41 void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
42 wxHtmlRenderingInfo& info);
43
44 wxDECLARE_NO_COPY_CLASS(wxHtmlListmarkCell);
45 };
46
47 wxHtmlListmarkCell::wxHtmlListmarkCell(wxDC* dc, const wxColour& clr) : wxHtmlCell(), m_Brush(clr, wxBRUSHSTYLE_SOLID)
48 {
49 m_Width = dc->GetCharHeight();
50 m_Height = dc->GetCharHeight();
51 // bottom of list mark is lined with bottom of letters in next cell
52 m_Descent = m_Height / 3;
53 }
54
55
56
57 void wxHtmlListmarkCell::Draw(wxDC& dc, int x, int y,
58 int WXUNUSED(view_y1), int WXUNUSED(view_y2),
59 wxHtmlRenderingInfo& WXUNUSED(info))
60 {
61 dc.SetBrush(m_Brush);
62 dc.DrawEllipse(x + m_PosX + m_Width / 3, y + m_PosY + m_Height / 3,
63 (m_Width / 3), (m_Width / 3));
64 }
65
66 //-----------------------------------------------------------------------------
67 // wxHtmlListCell
68 //-----------------------------------------------------------------------------
69
70 struct wxHtmlListItemStruct
71 {
72 wxHtmlContainerCell *mark;
73 wxHtmlContainerCell *cont;
74 int minWidth;
75 int maxWidth;
76 };
77
78 class wxHtmlListCell : public wxHtmlContainerCell
79 {
80 private:
81 wxBrush m_Brush;
82
83 int m_NumRows;
84 wxHtmlListItemStruct *m_RowInfo;
85 void ReallocRows(int rows);
86 void ComputeMinMaxWidths();
87 int ComputeMaxBase(wxHtmlCell *cell);
88 int m_ListmarkWidth;
89
90 public:
91 wxHtmlListCell(wxHtmlContainerCell *parent);
92 virtual ~wxHtmlListCell();
93 void AddRow(wxHtmlContainerCell *mark, wxHtmlContainerCell *cont);
94 virtual void Layout(int w);
95
96 wxDECLARE_NO_COPY_CLASS(wxHtmlListCell);
97 };
98
99 wxHtmlListCell::wxHtmlListCell(wxHtmlContainerCell *parent) : wxHtmlContainerCell(parent)
100 {
101 m_NumRows = 0;
102 m_RowInfo = 0;
103 m_ListmarkWidth = 0;
104 }
105
106 wxHtmlListCell::~wxHtmlListCell()
107 {
108 if (m_RowInfo) free(m_RowInfo);
109 }
110
111 int wxHtmlListCell::ComputeMaxBase(wxHtmlCell *cell)
112 {
113 if(!cell)
114 return 0;
115
116 wxHtmlCell *child = cell->GetFirstChild();
117
118 while(child)
119 {
120 int base = ComputeMaxBase( child );
121 if ( base > 0 ) return base + child->GetPosY();
122 child = child->GetNext();
123 }
124
125 return cell->GetHeight() - cell->GetDescent();
126 }
127
128 void wxHtmlListCell::Layout(int w)
129 {
130 wxHtmlCell::Layout(w);
131
132 ComputeMinMaxWidths();
133 m_Width = wxMax(m_Width, wxMin(w, GetMaxTotalWidth()));
134
135 int s_width = m_Width - m_IndentLeft;
136
137 int vpos = 0;
138 for (int r = 0; r < m_NumRows; r++)
139 {
140 // do layout first time to layout contents and adjust pos
141 m_RowInfo[r].mark->Layout(m_ListmarkWidth);
142 m_RowInfo[r].cont->Layout(s_width - m_ListmarkWidth);
143
144 const int base_mark = ComputeMaxBase( m_RowInfo[r].mark );
145 const int base_cont = ComputeMaxBase( m_RowInfo[r].cont );
146 const int adjust_mark = vpos + wxMax(base_cont-base_mark,0);
147 const int adjust_cont = vpos + wxMax(base_mark-base_cont,0);
148
149 m_RowInfo[r].mark->SetPos(m_IndentLeft, adjust_mark);
150 m_RowInfo[r].cont->SetPos(m_IndentLeft + m_ListmarkWidth, adjust_cont);
151
152 vpos = wxMax(adjust_mark + m_RowInfo[r].mark->GetHeight(),
153 adjust_cont + m_RowInfo[r].cont->GetHeight());
154 }
155 m_Height = vpos;
156 }
157
158 void wxHtmlListCell::AddRow(wxHtmlContainerCell *mark, wxHtmlContainerCell *cont)
159 {
160 ReallocRows(++m_NumRows);
161 m_RowInfo[m_NumRows - 1].mark = mark;
162 m_RowInfo[m_NumRows - 1].cont = cont;
163 }
164
165 void wxHtmlListCell::ReallocRows(int rows)
166 {
167 m_RowInfo = (wxHtmlListItemStruct*) realloc(m_RowInfo, sizeof(wxHtmlListItemStruct) * rows);
168 m_RowInfo[rows - 1].mark = NULL;
169 m_RowInfo[rows - 1].cont = NULL;
170 m_RowInfo[rows - 1].minWidth = 0;
171 m_RowInfo[rows - 1].maxWidth = 0;
172
173 m_NumRows = rows;
174 }
175
176 void wxHtmlListCell::ComputeMinMaxWidths()
177 {
178 if (m_NumRows == 0) return;
179
180 m_MaxTotalWidth = 0;
181 m_Width = 0;
182
183 for (int r = 0; r < m_NumRows; r++)
184 {
185 wxHtmlListItemStruct& row = m_RowInfo[r];
186 row.mark->Layout(1);
187 row.cont->Layout(1);
188 int maxWidth = row.cont->GetMaxTotalWidth();
189 int width = row.cont->GetWidth();
190 if (row.mark->GetWidth() > m_ListmarkWidth)
191 m_ListmarkWidth = row.mark->GetWidth();
192 if (maxWidth > m_MaxTotalWidth)
193 m_MaxTotalWidth = maxWidth;
194 if (width > m_Width)
195 m_Width = width;
196 }
197 m_Width += m_ListmarkWidth + m_IndentLeft;
198 m_MaxTotalWidth += m_ListmarkWidth + m_IndentLeft;
199 }
200
201 //-----------------------------------------------------------------------------
202 // wxHtmlListcontentCell
203 //-----------------------------------------------------------------------------
204
205 class wxHtmlListcontentCell : public wxHtmlContainerCell
206 {
207 public:
208 wxHtmlListcontentCell(wxHtmlContainerCell *p) : wxHtmlContainerCell(p) {}
209 virtual void Layout(int w) {
210 // Reset top indentation, fixes <li><p>
211 SetIndent(0, wxHTML_INDENT_TOP);
212 wxHtmlContainerCell::Layout(w);
213 }
214 };
215
216 //-----------------------------------------------------------------------------
217 // The list handler:
218 //-----------------------------------------------------------------------------
219
220
221 TAG_HANDLER_BEGIN(OLULLI, "OL,UL,LI")
222
223 TAG_HANDLER_VARS
224 wxHtmlListCell *m_List;
225 int m_Numbering;
226 // this is number of actual item of list or 0 for dots
227
228 TAG_HANDLER_CONSTR(OLULLI)
229 {
230 m_List = NULL;
231 m_Numbering = 0;
232 }
233
234 TAG_HANDLER_PROC(tag)
235 {
236 wxHtmlContainerCell *c;
237
238 // List Item:
239 if (m_List && tag.GetName() == wxT("LI"))
240 {
241 c = m_WParser->SetContainer(new wxHtmlContainerCell(m_List));
242 c->SetAlignVer(wxHTML_ALIGN_TOP);
243
244 wxHtmlContainerCell *mark = c;
245 c->SetWidthFloat(2 * m_WParser->GetCharWidth(), wxHTML_UNITS_PIXELS);
246 if (m_Numbering == 0)
247 {
248 // Centering gives more space after the bullet
249 c->SetAlignHor(wxHTML_ALIGN_CENTER);
250 c->InsertCell(new wxHtmlListmarkCell(m_WParser->GetDC(), m_WParser->GetActualColor()));
251 }
252 else
253 {
254 c->SetAlignHor(wxHTML_ALIGN_RIGHT);
255 wxString markStr;
256 markStr.Printf(wxT("%i. "), m_Numbering);
257 c->InsertCell(new wxHtmlWordCell(markStr, *(m_WParser->GetDC())));
258 }
259 m_WParser->CloseContainer();
260
261 c = m_WParser->OpenContainer();
262
263 m_List->AddRow(mark, c);
264 c = m_WParser->OpenContainer();
265 m_WParser->SetContainer(new wxHtmlListcontentCell(c));
266
267 if (m_Numbering != 0) m_Numbering++;
268 }
269
270 // Begin of List (not-numbered): "UL", "OL"
271 else if (tag.GetName() == wxT("UL") || tag.GetName() == wxT("OL"))
272 {
273 int oldnum = m_Numbering;
274
275 if (tag.GetName() == wxT("UL")) m_Numbering = 0;
276 else m_Numbering = 1;
277
278 wxHtmlContainerCell *oldcont;
279 oldcont = c = m_WParser->OpenContainer();
280
281 wxHtmlListCell *oldList = m_List;
282 m_List = new wxHtmlListCell(c);
283 m_List->SetIndent(2 * m_WParser->GetCharWidth(), wxHTML_INDENT_LEFT);
284
285 ParseInner(tag);
286
287 m_WParser->SetContainer(oldcont);
288 m_WParser->CloseContainer();
289
290 m_Numbering = oldnum;
291 m_List = oldList;
292 return true;
293 }
294 return false;
295
296 }
297
298 TAG_HANDLER_END(OLULLI)
299
300
301 TAGS_MODULE_BEGIN(List)
302
303 TAGS_MODULE_ADD(OLULLI)
304
305 TAGS_MODULE_END(List)
306
307 #endif