Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: ui/uilib/static_ex.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/uilib/static_ex.h ('k') | ui/uilib/static_line.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2006-2009 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15 //
16
17 // TODO(omaha): need to handle WM_GETTEXT
18 // TODO(omaha): need to handle WM_SIZE
19 // TODO(omaha): nice to have transparent mode
20
21 #include "omaha/ui/uilib/static_ex.h"
22
23 #include <shellapi.h>
24 #include <strsafe.h>
25 #include "omaha/ui/uilib/node_state.h"
26
27 const int StaticEx::kBorderNone = 0;
28 const int StaticEx::kBorderLeft = 1;
29 const int StaticEx::kBorderTop = 2;
30 const int StaticEx::kBorderRight = 4;
31 const int StaticEx::kBorderBottom = 8;
32 const int StaticEx::kBorderAll = kBorderLeft | kBorderTop | kBorderRight |
33 kBorderBottom;
34
35 HCURSOR StaticEx::hand_cursor_ = NULL;
36
37 StaticEx::StaticEx()
38 : margins_(1, 0, 1, 0), // see comment in h file
39 background_color_(0xffffff),
40 use_background_color_(false),
41 ellipsis_(0),
42 border_(kBorderNone),
43 border_color_(0),
44 default_font_(NULL) {
45 }
46
47 StaticEx::~StaticEx() {
48 EraseNodes();
49 EraseLines(&lines_);
50 }
51
52 void StaticEx::Reset() {
53 text_.Empty();
54 EraseNodes();
55 EraseLines(&lines_);
56 default_font_ = NULL;
57 }
58
59 BOOL StaticEx::SubclassWindow(HWND window) {
60 Reset();
61 // first get text from exising control
62 unsigned length = ::SendMessage(window, WM_GETTEXTLENGTH, 0, 0);
63 CString text;
64 if (length > 0) {
65 TCHAR* buffer = text.GetBufferSetLength(length);
66 ::SendMessage(window,
67 WM_GETTEXT,
68 length + 1,
69 reinterpret_cast<LPARAM>(buffer));
70 text.ReleaseBuffer(-1);
71 }
72
73 // then subclass
74 BOOL result = CWindowImpl<StaticEx>::SubclassWindow(window);
75
76 // set text back (it will parse it and replace text in subclassed control
77 // with readble text)
78 if (result && length > 0) {
79 SetWindowText(text);
80 }
81
82 return result;
83 }
84
85 HWND StaticEx::UnsubclassWindow(BOOL force /*= FALSE*/) {
86 Reset(); // clean up an old state
87 return CWindowImpl<StaticEx>::UnsubclassWindow(force);
88 }
89
90 LRESULT StaticEx::OnSetText(UINT msg, WPARAM wparam, LPARAM lparam,
91 BOOL& handled) {
92 // parse text first, because we will need to get "readable" text
93 text_ = reinterpret_cast<const TCHAR*>(lparam);
94 ParseText();
95
96 // set readable text to subclassed control, this text will be return by
97 // GetWindowText() or WM_GETTEXT. (when GetWindowText is called from another
98 // process it doesn't send WM_GETTEXT but reads text directly from contol)
99 // so we need to set text to it.
100 // Disable redraw, without it calling DefWindowProc would redraw control
101 // immediately without sending WM_PAINT message
102 SetRedraw(FALSE);
103 DefWindowProc(msg, wparam,
104 reinterpret_cast<LPARAM>(static_cast<const TCHAR*>(GetReadableText())));
105 SetRedraw(TRUE);
106
107 // now invalidate to display new text
108 Invalidate();
109
110 handled = TRUE;
111 return 1;
112 }
113
114 LRESULT StaticEx::OnGetText(UINT, WPARAM wparam, LPARAM lparam, BOOL& handled) { // NOLINT
115 if (!lparam) return 0;
116 unsigned size = static_cast<unsigned>(wparam);
117 TCHAR* buffer = reinterpret_cast<TCHAR*>(lparam);
118
119 handled = TRUE;
120 unsigned my_size = text_.GetLength();
121 if (my_size < size) {
122 StringCchCopy(buffer, size, text_);
123 return my_size;
124 }
125
126 StringCchCopyN(buffer, size, text_, size - 1);
127 buffer[size - 1] = 0;
128
129 return size - 1;
130 }
131
132 LRESULT StaticEx::OnGetTextLength(UINT, WPARAM, LPARAM, BOOL& handled) { // NOL INT
133 handled = TRUE;
134 return text_.GetLength();
135 }
136
137 void StaticEx::set_background_color(COLORREF back_color) {
138 background_color_ = back_color;
139 use_background_color_ = true;
140 Invalidate();
141 }
142
143 void StaticEx::set_margins(const RECT& rect) {
144 margins_ = rect;
145 Invalidate();
146 }
147
148 void StaticEx::set_margins(int left, int top, int right, int bottom) {
149 margins_.SetRect(left, top, right, bottom);
150 Invalidate();
151 }
152
153
154 LRESULT StaticEx::OnLButtonUp(UINT, WPARAM, LPARAM lparam, BOOL&) {
155 CPoint point(LOWORD(lparam), HIWORD(lparam));
156
157 int height = margins_.top + (border_ & kBorderTop) ? 1 : 0;
158 size_t size = lines_.size();
159 for (size_t i = 0; i < size; i++) {
160 height += lines_[i]->height();
161 if (point.y < height) {
162 CString action;
163 if (lines_[i]->IsUrlUnderMouse(point, &action) && !action.IsEmpty()) {
164 // Notify the parent window to handle the click.
165 LRESULT handled = 0;
166 NMSTATICEX notification = {0};
167 notification.header.hwndFrom = m_hWnd;
168 notification.header.idFrom = GetDlgCtrlID();
169 notification.header.code = NM_STATICEX;
170 notification.action = action;
171
172 HWND parent = GetParent();
173 if (parent) {
174 handled = ::SendMessage(parent, WM_NOTIFY, notification.header.idFrom,
175 reinterpret_cast<LPARAM>(&notification));
176 ATLASSERT(handled);
177 }
178 }
179 break;
180 }
181 }
182 return 0;
183 }
184
185
186 LRESULT StaticEx::OnSetCursor(UINT, WPARAM, LPARAM lparam, BOOL& handled) { // NOLINT
187 int hit_test = LOWORD(lparam);
188 handled = FALSE;
189 if (hit_test != HTCLIENT) {
190 return 0;
191 }
192
193 POINT position;
194 if (!GetCursorPos(&position))
195 return 0;
196
197 ScreenToClient(&position);
198
199 int offset = margins_.top + (border_ & kBorderTop) ? 1 : 0;
200 size_t size = lines_.size();
201 for (size_t i = 0; i < size; i++) {
202 offset += lines_[i]->height();
203 if (position.y < offset) {
204 if (lines_[i]->IsUrlUnderMouse(position, NULL)) {
205 ::SetCursor(GetHandCursor());
206 handled = TRUE;
207 }
208 break;
209 }
210 }
211
212 return 0;
213 }
214
215 void StaticEx::set_ellipsis(int ellipsis) {
216 if (ellipsis == DT_END_ELLIPSIS ||
217 ellipsis == DT_WORD_ELLIPSIS ||
218 ellipsis == DT_PATH_ELLIPSIS ||
219 ellipsis == 0) {
220 ellipsis_ = ellipsis;
221 if (ellipsis != 0)
222 ModifyStyle(0, SS_LEFTNOWORDWRAP);
223 Invalidate();
224 }
225 }
226
227 void StaticEx::set_border(int border) {
228 border_ = border;
229 Invalidate();
230 }
231
232 void StaticEx::set_border_color(COLORREF border_color) {
233 border_color_ = border_color;
234 Invalidate();
235 }
236
237 void StaticEx::ParseText() {
238 EraseNodes();
239 EraseLines(&lines_);
240
241 if (text_.IsEmpty())
242 return;
243
244 if (!default_font_)
245 default_font_ = GetFont();
246
247 NodeState node_state(m_hWnd);
248 node_state.SetStdFont(default_font_);
249
250 const TCHAR* current_string = text_;
251 int current_offset = 0;
252 bool had_good_tag = true;
253 while (*current_string) {
254 current_offset = 0;
255
256 if (had_good_tag) {
257 // if it was a good tag we consumed it and need to start with a new node
258 Node* node = new Node(m_hWnd);
259 nodes_.push_back(node);
260
261 // -1 if there is no Open Bracket "<"
262 current_offset = FindOpenBracket(current_string);
263
264 if (current_offset < 0) {
265 // no tags left, just plain text
266 node->AddText(current_string);
267 node->set_node_state(node_state);
268 break;
269 }
270
271 if (*current_string != _T('<')) {
272 // has some text before the tag
273 node->AddText(CString(current_string, current_offset));
274 node->set_node_state(node_state);
275 current_string += current_offset;
276 continue;
277 }
278
279 int next_offset = node_state.ConsumeTag(current_string + current_offset);
280
281 if (next_offset > 0) {
282 // it was a known tag
283 had_good_tag = true;
284 current_string += current_offset + next_offset;
285 } else {
286 // unknown tag, will keep looking
287 had_good_tag = false;
288 node->AddText(CString(current_string, current_offset + 1));
289 node->set_node_state(node_state);
290 current_string += current_offset + 1;
291 continue;
292 }
293 } else {
294 had_good_tag = true;
295 }
296 delete nodes_.back();
297 nodes_.pop_back();
298 }
299 }
300
301 CString StaticEx::GetReadableText() {
302 CString text;
303 for (size_t i = 0; i < nodes_.size(); i++) {
304 text += nodes_[i]->node_text();
305 }
306 return text;
307 }
308
309 void StaticEx::EraseNodes() {
310 for (size_t i = 0; i < nodes_.size(); ++i) {
311 delete nodes_[i];
312 }
313 nodes_.clear();
314 }
315
316 void StaticEx::EraseLines(std::vector<StaticLine*>* lines) {
317 size_t size = lines->size();
318 for (size_t i = 0; i < size; i++) {
319 delete (*lines)[i];
320 }
321 lines->clear();
322 }
323
324 int StaticEx::FindOpenBracket(const TCHAR* string) {
325 const TCHAR* left_bracket = _tcschr(string, _T('<'));
326
327 if (left_bracket == NULL)
328 return -1;
329
330 return static_cast<int>(left_bracket - string);
331 }
332
333 LRESULT StaticEx::OnPaint(UINT, WPARAM, LPARAM, BOOL&) {
334 PAINTSTRUCT paint_struct;
335 HDC hdc = BeginPaint(&paint_struct);
336
337 CRect client_rect;
338 GetClientRect(&client_rect);
339
340 CRect working_rect(client_rect);
341
342 working_rect.DeflateRect(margins_);
343 working_rect.DeflateRect((border_ & kBorderLeft) ? 1 : 0,
344 (border_ & kBorderTop) ? 1 : 0,
345 (border_ & kBorderRight) ? 1 : 0,
346 (border_ & kBorderBottom) ? 1 : 0);
347
348 DWORD style = GetStyle();
349
350 EraseLines(&lines_);
351 PrePaint(hdc, &lines_, nodes_, working_rect, style, ellipsis_);
352
353 if (use_background_color_) {
354 FillRect(hdc, &client_rect, CreateSolidBrush(background_color_));
355 } else {
356 HBRUSH brush = reinterpret_cast<HBRUSH>(::SendMessage(GetParent(),
357 WM_CTLCOLORSTATIC, reinterpret_cast<WPARAM>(hdc),
358 reinterpret_cast<LPARAM>(m_hWnd)));
359 if (brush) {
360 ::FillRect(hdc, &client_rect, brush);
361 }
362 }
363
364 if (border_ != kBorderNone)
365 DrawBorder(hdc, client_rect);
366
367 Paint(hdc, lines_, working_rect, style, ellipsis_);
368
369 EndPaint(&paint_struct);
370 return 0;
371 }
372
373 void StaticEx::PrePaint(HDC hdc, std::vector<StaticLine*>* lines,
374 const std::vector<Node*>& nodes, RECT rect, DWORD style,
375 int ellipsis) {
376 if (nodes.empty())
377 return;
378
379 int x = 0;
380 int width = rect.right - rect.left;
381 StaticLine* line = new StaticLine;
382 lines->push_back(line);
383 bool done = false;
384 size_t size = nodes.size();
385 for (size_t i = 0; i < size; ++i) {
386 Node* node = nodes[i];
387 const NodeState& node_state = node->node_state();
388 CString text = node->node_text();
389 int string_len = text.GetLength();
390
391 HFONT font = node_state.GetFont();
392 if (!font)
393 return;
394
395 HFONT old_font = static_cast<HFONT>(SelectObject(hdc, font));
396
397 TEXTMETRIC text_metrics;
398 GetTextMetrics(hdc, &text_metrics);
399
400 int height = text_metrics.tmHeight + text_metrics.tmExternalLeading;
401 int base_line = text_metrics.tmHeight + text_metrics.tmExternalLeading -
402 text_metrics.tmDescent;
403 line->AdjustHeight(height);
404 line->AdjustBaseLine(base_line);
405
406 bool single_line = (style & SS_LEFTNOWORDWRAP) != 0;
407
408 int current_pos = 0;
409 bool more_left = false;
410 while (true) {
411 int current_length = string_len - current_pos;
412
413 // find LF if any
414 int lf_position = text.Find(_T('\n'), current_pos);
415 if (lf_position == current_pos) {
416 if (single_line) {
417 if (ellipsis)
418 line->AddEllipses();
419 break;
420 }
421 line = new StaticLine;
422 lines->push_back(line);
423 line->AdjustHeight(height);
424 line->AdjustBaseLine(base_line);
425 x = 0;
426
427 current_pos++;
428
429 continue;
430 } else if (lf_position > 0) {
431 current_length = lf_position - current_pos;
432 more_left = true;
433 }
434
435 // check if it will fit in one line
436 int fit = 0;
437 SIZE string_size;
438 GetTextExtentExPoint(hdc, static_cast<const TCHAR*>(text) + current_pos,
439 current_length, width - x, &fit, NULL, &string_size);
440
441 if (fit < current_length) {
442 // string doesn't fit, need to move to the next line
443 // find last space
444 int fit_saved = fit;
445 for (; fit > 0; fit--) {
446 if (text.GetAt(current_pos + fit) == _T(' ')) {
447 break;
448 }
449 }
450
451 // if a first word of a node doesn't fit and it starts in a first half
452 // of control then wrap the word on a last char that fits
453 // otherwise move whole node to the next line
454 if ((fit <= 0) && (x < width / 2))
455 fit = fit_saved;
456
457 if (fit > 0) {
458 line->AddNode(node, current_pos, fit, height, base_line, width - x);
459 }
460
461 if (single_line) {
462 if (ellipsis)
463 line->AddEllipses();
464 done = true;
465 break;
466 }
467 line = new StaticLine;
468 lines->push_back(line);
469 line->AdjustHeight(height);
470 line->AdjustBaseLine(base_line);
471 x = 0;
472
473 current_pos += fit;
474 // skip spaces
475 while (text.GetAt(current_pos) == _T(' '))
476 current_pos++;
477 continue;
478 } else {
479 line->AddNode(node, current_pos, fit, height, base_line,
480 string_size.cx);
481 }
482
483 // done, it fits
484 x += string_size.cx;
485 if (!more_left)
486 break;
487
488 current_pos += current_length;
489 more_left = false;
490 }
491
492 if (old_font)
493 SelectObject(hdc, old_font);
494
495 if (done)
496 break;
497 }
498 }
499
500
501 void StaticEx::Paint(HDC hdc, const std::vector<StaticLine*>& lines, RECT rect,
502 DWORD style, int ellipsis) {
503 if ((style & SS_LEFTNOWORDWRAP) == 0) {
504 ellipsis = 0;
505 }
506
507 size_t size = lines.size();
508 int y = rect.top;
509 for (size_t i = 0; i < size; i++) {
510 int height = lines[i]->Paint(hdc, rect.left, rect.right, y, style,
511 ellipsis);
512 y += height;
513 }
514 }
515
516 LRESULT StaticEx::OnEraseBkgnd(UINT /*msg*/, WPARAM /*wparam*/,
517 LPARAM /*lparam*/, BOOL& handled) {
518 handled = TRUE;
519 return 0;
520 }
521
522 void StaticEx::DrawBorder(HDC hdc, const CRect& rect) {
523 HGDIOBJ old_object = SelectObject(hdc, GetStockObject(DC_PEN));
524 SetDCPenColor(hdc, border_color_);
525 if (border_ & kBorderLeft) {
526 MoveToEx(hdc, rect.left, rect.top, NULL);
527 LineTo(hdc, rect.left, rect.bottom);
528 }
529 if (border_ & kBorderTop) {
530 MoveToEx(hdc, rect.left, rect.top, NULL);
531 LineTo(hdc, rect.right, rect.top);
532 }
533 if (border_ & kBorderRight) {
534 MoveToEx(hdc, rect.right - 1, rect.top, NULL);
535 LineTo(hdc, rect.right - 1, rect.bottom);
536 }
537 if (border_ & kBorderBottom) {
538 MoveToEx(hdc, rect.left, rect.bottom - 1, NULL);
539 LineTo(hdc, rect.right, rect.bottom - 1);
540 }
541 SelectObject(hdc, old_object);
542 }
543
544 int StaticEx::GetMinimumHeight(int width) {
545 HDC device_context = CreateCompatibleDC(NULL);
546
547 CRect client_rect;
548 if (width <= 0)
549 GetClientRect(&client_rect);
550 else
551 client_rect.SetRect(0, 0, width, 100); // last value is not used
552
553 CRect working_rect(client_rect);
554
555 working_rect.DeflateRect(margins_);
556 working_rect.DeflateRect((border_ & kBorderLeft) ? 1 : 0,
557 (border_ & kBorderTop) ? 1 : 0,
558 (border_ & kBorderRight) ? 1 : 0,
559 (border_ & kBorderBottom) ? 1 : 0);
560
561 DWORD style = GetStyle();
562
563 std::vector<StaticLine*> lines;
564 PrePaint(device_context, &lines, nodes_, working_rect, style, ellipsis_);
565
566 DeleteDC(device_context);
567
568 int height = 0;
569 for (unsigned i = 0; i < lines.size(); i++) {
570 height += lines[i]->height();
571 }
572 height += margins_.top + margins_.bottom;
573 height += (border_ & kBorderTop) ? 1 : 0;
574 height += (border_ & kBorderBottom) ? 1 : 0;
575
576 return height;
577 }
578
579
580 HCURSOR StaticEx::GetHandCursor() {
581 if (hand_cursor_ == NULL) {
582 // Load cursor resource
583 hand_cursor_ = (HCURSOR)LoadCursor(NULL, IDC_HAND); // doesn't work on NT4!
584 }
585 return hand_cursor_;
586 }
OLDNEW
« no previous file with comments | « ui/uilib/static_ex.h ('k') | ui/uilib/static_line.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698