btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / apps / webpositive / URLInputGroup.cpp
blob9a0437e9ae99a92fbfc0230c78d6c65f0dc8c363
1 /*
2 * Copyright 2010 Stephan Aßmus <superstippi@gmx.de>
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
6 #include "URLInputGroup.h"
8 #include <Bitmap.h>
9 #include <Button.h>
10 #include <Catalog.h>
11 #include <ControlLook.h>
12 #include <Clipboard.h>
13 #include <GroupLayout.h>
14 #include <GroupLayoutBuilder.h>
15 #include <Locale.h>
16 #include <LayoutUtils.h>
17 #include <MenuItem.h>
18 #include <PopUpMenu.h>
19 #include <SeparatorView.h>
20 #include <TextView.h>
21 #include <Window.h>
23 #include <stdio.h>
24 #include <stdlib.h>
26 #include "BaseURL.h"
27 #include "BitmapButton.h"
28 #include "BrowsingHistory.h"
29 #include "IconButton.h"
30 #include "IconUtils.h"
31 #include "TextViewCompleter.h"
34 #undef B_TRANSLATION_CONTEXT
35 #define B_TRANSLATION_CONTEXT "URL Bar"
38 class URLChoice : public BAutoCompleter::Choice {
39 public:
40 URLChoice(const BString& choiceText, const BString& displayText,
41 int32 matchPos, int32 matchLen, int32 priority)
43 BAutoCompleter::Choice(choiceText, displayText, matchPos, matchLen),
44 fPriority(priority)
48 bool operator<(const URLChoice& other) const
50 if (fPriority > other.fPriority)
51 return true;
52 return DisplayText() < other.DisplayText();
55 bool operator==(const URLChoice& other) const
57 return fPriority == other.fPriority
58 && DisplayText() < other.DisplayText();
61 private:
62 int32 fPriority;
66 class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel {
67 virtual void FetchChoicesFor(const BString& pattern)
69 int32 count = CountChoices();
70 for (int32 i = 0; i < count; i++) {
71 delete reinterpret_cast<BAutoCompleter::Choice*>(
72 fChoices.ItemAtFast(i));
74 fChoices.MakeEmpty();
76 // Search through BrowsingHistory for any matches.
77 BrowsingHistory* history = BrowsingHistory::DefaultInstance();
78 if (!history->Lock())
79 return;
81 BString lastBaseURL;
82 int32 priority = INT_MAX;
84 count = history->CountItems();
85 for (int32 i = 0; i < count; i++) {
86 BrowsingHistoryItem item = history->HistoryItemAt(i);
87 const BString& choiceText = item.URL();
88 int32 matchPos = choiceText.IFindFirst(pattern);
89 if (matchPos < 0)
90 continue;
91 if (lastBaseURL.Length() > 0
92 && choiceText.FindFirst(lastBaseURL) >= 0) {
93 priority--;
94 } else
95 priority = INT_MAX;
96 lastBaseURL = baseURL(choiceText);
97 fChoices.AddItem(new URLChoice(choiceText,
98 choiceText, matchPos, pattern.Length(), priority));
101 history->Unlock();
103 fChoices.SortItems(_CompareChoices);
106 virtual int32 CountChoices() const
108 return fChoices.CountItems();
111 virtual const BAutoCompleter::Choice* ChoiceAt(int32 index) const
113 return reinterpret_cast<BAutoCompleter::Choice*>(
114 fChoices.ItemAt(index));
117 static int _CompareChoices(const void* a, const void* b)
119 const URLChoice* aChoice
120 = *reinterpret_cast<const URLChoice* const *>(a);
121 const URLChoice* bChoice
122 = *reinterpret_cast<const URLChoice* const *>(b);
123 if (*aChoice < *bChoice)
124 return -1;
125 else if (*aChoice == *bChoice)
126 return 0;
127 return 1;
130 private:
131 BList fChoices;
135 // #pragma mark - URLTextView
138 static const float kHorizontalTextRectInset = 4.0;
141 class URLInputGroup::URLTextView : public BTextView {
142 private:
143 static const uint32 MSG_CLEAR = 'cler';
145 public:
146 URLTextView(URLInputGroup* parent);
147 virtual ~URLTextView();
149 virtual void MessageReceived(BMessage* message);
150 virtual void FrameResized(float width, float height);
151 virtual void MouseDown(BPoint where);
152 virtual void KeyDown(const char* bytes, int32 numBytes);
153 virtual void MakeFocus(bool focused = true);
155 virtual BSize MinSize();
156 virtual BSize MaxSize();
158 void SetUpdateAutoCompleterChoices(bool update);
160 protected:
161 virtual void InsertText(const char* inText, int32 inLength,
162 int32 inOffset,
163 const text_run_array* inRuns);
164 virtual void DeleteText(int32 fromOffset, int32 toOffset);
166 private:
167 void _AlignTextRect();
169 private:
170 URLInputGroup* fURLInputGroup;
171 TextViewCompleter* fURLAutoCompleter;
172 bool fUpdateAutoCompleterChoices;
176 URLInputGroup::URLTextView::URLTextView(URLInputGroup* parent)
178 BTextView("url"),
179 fURLInputGroup(parent),
180 fURLAutoCompleter(new TextViewCompleter(this,
181 new BrowsingHistoryChoiceModel())),
182 fUpdateAutoCompleterChoices(true)
184 MakeResizable(true);
185 SetStylable(true);
186 fURLAutoCompleter->SetModificationsReported(true);
190 URLInputGroup::URLTextView::~URLTextView()
192 delete fURLAutoCompleter;
196 void
197 URLInputGroup::URLTextView::MessageReceived(BMessage* message)
199 switch (message->what) {
200 case MSG_CLEAR:
201 SetText("");
202 break;
204 default:
205 BTextView::MessageReceived(message);
206 break;
211 void
212 URLInputGroup::URLTextView::FrameResized(float width, float height)
214 BTextView::FrameResized(width, height);
215 _AlignTextRect();
219 void
220 URLInputGroup::URLTextView::MouseDown(BPoint where)
222 bool wasFocus = IsFocus();
223 if (!wasFocus)
224 MakeFocus(true);
226 int32 buttons;
227 if (Window()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK)
228 buttons = B_PRIMARY_MOUSE_BUTTON;
230 if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) {
231 // Display context menu
232 int32 selectionStart;
233 int32 selectionEnd;
234 GetSelection(&selectionStart, &selectionEnd);
235 bool canCutOrCopy = selectionEnd > selectionStart;
237 bool canPaste = false;
238 if (be_clipboard->Lock()) {
239 if (BMessage* data = be_clipboard->Data())
240 canPaste = data->HasData("text/plain", B_MIME_TYPE);
241 be_clipboard->Unlock();
244 BMenuItem* cutItem = new BMenuItem(B_TRANSLATE("Cut"),
245 new BMessage(B_CUT));
246 BMenuItem* copyItem = new BMenuItem(B_TRANSLATE("Copy"),
247 new BMessage(B_COPY));
248 BMenuItem* pasteItem = new BMenuItem(B_TRANSLATE("Paste"),
249 new BMessage(B_PASTE));
250 BMenuItem* clearItem = new BMenuItem(B_TRANSLATE("Clear"),
251 new BMessage(MSG_CLEAR));
252 cutItem->SetEnabled(canCutOrCopy);
253 copyItem->SetEnabled(canCutOrCopy);
254 pasteItem->SetEnabled(canPaste);
255 clearItem->SetEnabled(strlen(Text()) > 0);
257 BPopUpMenu* menu = new BPopUpMenu("url context");
258 menu->AddItem(cutItem);
259 menu->AddItem(copyItem);
260 menu->AddItem(pasteItem);
261 menu->AddItem(clearItem);
263 menu->SetTargetForItems(this);
264 menu->Go(ConvertToScreen(where), true, true, true);
265 return;
268 // Only pass through to base class if we already have focus.
269 if (!wasFocus)
270 return;
272 BTextView::MouseDown(where);
276 void
277 URLInputGroup::URLTextView::KeyDown(const char* bytes, int32 numBytes)
279 switch (bytes[0]) {
280 case B_TAB:
281 BView::KeyDown(bytes, numBytes);
282 break;
284 case B_ESCAPE:
285 // Text already unlocked && replaced in BrowserWindow,
286 // now select it.
287 SelectAll();
288 break;
290 case B_RETURN:
291 // Don't let this through to the text view.
292 break;
294 default:
296 BString currentText = Text();
297 BTextView::KeyDown(bytes, numBytes);
298 // Lock the URL input if it was modified
299 if (!fURLInputGroup->IsURLInputLocked()
300 && Text() != currentText)
301 fURLInputGroup->LockURLInput();
302 break;
307 void
308 URLInputGroup::URLTextView::MakeFocus(bool focus)
310 // Unlock the URL input if focus was lost.
311 if (!focus)
312 fURLInputGroup->LockURLInput(false);
314 if (focus == IsFocus())
315 return;
317 BTextView::MakeFocus(focus);
319 if (focus)
320 SelectAll();
322 fURLInputGroup->Invalidate();
326 BSize
327 URLInputGroup::URLTextView::MinSize()
329 BSize min;
330 min.height = ceilf(LineHeight(0) + kHorizontalTextRectInset);
331 // we always add at least one pixel vertical inset top/bottom for
332 // the text rect.
333 min.width = min.height * 3;
334 return BLayoutUtils::ComposeSize(ExplicitMinSize(), min);
338 BSize
339 URLInputGroup::URLTextView::MaxSize()
341 BSize max(MinSize());
342 max.width = B_SIZE_UNLIMITED;
343 return BLayoutUtils::ComposeSize(ExplicitMaxSize(), max);
347 void
348 URLInputGroup::URLTextView::SetUpdateAutoCompleterChoices(bool update)
350 fUpdateAutoCompleterChoices = update;
354 void
355 URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength,
356 int32 inOffset, const text_run_array* inRuns)
358 // Filter all line breaks, note that inText is not terminated.
359 if (inLength == 1) {
360 if (*inText == '\n' || *inText == '\r')
361 BTextView::InsertText(" ", 1, inOffset, inRuns);
362 else
363 BTextView::InsertText(inText, 1, inOffset, inRuns);
364 } else {
365 BString filteredText(inText, inLength);
366 filteredText.ReplaceAll('\n', ' ');
367 filteredText.ReplaceAll('\r', ' ');
368 BTextView::InsertText(filteredText.String(), inLength, inOffset,
369 inRuns);
372 // Make the base URL part bold.
373 BString text(Text(), TextLength());
374 int32 baseUrlStart = text.FindFirst("://");
375 if (baseUrlStart >= 0)
376 baseUrlStart += 3;
377 else
378 baseUrlStart = 0;
379 int32 baseUrlEnd = text.FindFirst("/", baseUrlStart);
380 if (baseUrlEnd < 0)
381 baseUrlEnd = TextLength();
383 BFont font;
384 GetFont(&font);
385 const rgb_color black = (rgb_color) { 0, 0, 0, 255 };
386 const rgb_color gray = (rgb_color) { 60, 60, 60, 255 };
387 if (baseUrlStart > 0)
388 SetFontAndColor(0, baseUrlStart, &font, B_FONT_ALL, &gray);
389 if (baseUrlEnd > baseUrlStart) {
390 font.SetFace(B_BOLD_FACE);
391 SetFontAndColor(baseUrlStart, baseUrlEnd, &font, B_FONT_ALL, &black);
393 if (baseUrlEnd < TextLength()) {
394 font.SetFace(B_REGULAR_FACE);
395 SetFontAndColor(baseUrlEnd, TextLength(), &font, B_FONT_ALL, &gray);
398 fURLAutoCompleter->TextModified(fUpdateAutoCompleterChoices);
402 void
403 URLInputGroup::URLTextView::DeleteText(int32 fromOffset, int32 toOffset)
405 BTextView::DeleteText(fromOffset, toOffset);
407 fURLAutoCompleter->TextModified(fUpdateAutoCompleterChoices);
411 void
412 URLInputGroup::URLTextView::_AlignTextRect()
414 // Layout the text rect to be in the middle, normally this means there
415 // is one pixel spacing on each side.
416 BRect textRect(Bounds());
417 textRect.left = 0.0;
418 float vInset = max_c(1,
419 floorf((textRect.Height() - LineHeight(0)) / 2.0 + 0.5));
420 float hInset = kHorizontalTextRectInset;
422 if (be_control_look)
423 hInset = be_control_look->DefaultLabelSpacing();
425 textRect.InsetBy(hInset, vInset);
426 SetTextRect(textRect);
430 const uint32 kGoBitmapWidth = 14;
431 const uint32 kGoBitmapHeight = 14;
432 const color_space kGoBitmapFormat = B_RGBA32;
434 const unsigned char kGoBitmapBits[] = {
435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21,
447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, 0x50, 0x50, 0x50, 0xff,
454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0,
457 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 0x00, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x2f, 0x56, 0x50, 0x50, 0x50, 0xff, 0x4d, 0x4d, 0x4d, 0xed,
459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21,
460 0x49, 0x49, 0x49, 0xe0, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
461 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
462 0x50, 0x50, 0x50, 0xff, 0x37, 0x37, 0x37, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, 0x50, 0x50, 0x50, 0xff,
464 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
465 0x50, 0x50, 0x50, 0xff, 0x4b, 0x4b, 0x4b, 0xec, 0x37, 0x37, 0x37, 0x77, 0x00, 0x00, 0x00, 0x02,
466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe1, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21,
471 0x49, 0x49, 0x49, 0xe1, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe1,
475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
487 const unsigned char kPlaceholderIcon[] = {
488 0x6e, 0x63, 0x69, 0x66, 0x04, 0x04, 0x00, 0x66, 0x03, 0x00, 0x3f, 0x80,
489 0x02, 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x3d, 0xa6, 0x64, 0xc2, 0x19,
490 0x98, 0x00, 0x00, 0x00, 0x4d, 0xce, 0x64, 0x49, 0xac, 0xcc, 0x00, 0xab,
491 0xd5, 0xff, 0xff, 0x00, 0x6c, 0xd9, 0x02, 0x00, 0x06, 0x02, 0x00, 0x00,
492 0x00, 0x3d, 0x26, 0x64, 0xc2, 0x19, 0x98, 0x00, 0x00, 0x00, 0x4d, 0xce,
493 0x64, 0x49, 0xac, 0xcc, 0x00, 0x80, 0xff, 0x80, 0xff, 0x00, 0xb2, 0x00,
494 0x04, 0x02, 0x04, 0x34, 0x22, 0xbd, 0x9b, 0x22, 0xb8, 0x53, 0x22, 0x28,
495 0x2e, 0x28, 0xb5, 0xef, 0x28, 0xbb, 0x37, 0x34, 0x3a, 0xb8, 0x53, 0x3a,
496 0xbd, 0x9b, 0x3a, 0x40, 0x2e, 0x40, 0xbb, 0x37, 0x40, 0xb5, 0xef, 0x02,
497 0x08, 0xbe, 0xb6, 0xb4, 0xac, 0xc1, 0x46, 0xb4, 0xac, 0xbc, 0x25, 0xb4,
498 0xac, 0xb8, 0x09, 0xb7, 0x35, 0xb9, 0xcf, 0xb5, 0xa0, 0xb8, 0x05, 0xbe,
499 0xb6, 0x35, 0xc2, 0xe5, 0x35, 0xbe, 0xb6, 0x35, 0xc5, 0x68, 0xb8, 0x09,
500 0xc6, 0x36, 0xb8, 0x09, 0xc6, 0x36, 0xb9, 0xcf, 0xc7, 0xca, 0xbe, 0xb6,
501 0xc8, 0xc1, 0xbc, 0x25, 0xc8, 0xc1, 0xc1, 0xb3, 0xc8, 0xc1, 0xc6, 0x3c,
502 0xc5, 0x5b, 0xc4, 0x65, 0xc7, 0x70, 0xc6, 0x3e, 0xbe, 0xb6, 0xc2, 0x0f,
503 0xba, 0x87, 0xc2, 0x0f, 0xbe, 0xb6, 0xc2, 0x0f, 0xb8, 0x05, 0xc5, 0x64,
504 0xb7, 0x37, 0xc5, 0x64, 0xb7, 0x37, 0xc3, 0x9e, 0xb5, 0xa2, 0x02, 0x04,
505 0xb8, 0x09, 0xb7, 0x35, 0xb8, 0x05, 0xbe, 0xb6, 0xb5, 0xf8, 0xb9, 0x0c,
506 0xb4, 0xac, 0xbe, 0xb6, 0xb4, 0xac, 0xbb, 0xba, 0xb4, 0xac, 0xc1, 0xb1,
507 0xb8, 0x09, 0xc6, 0x36, 0xb5, 0xf8, 0xc4, 0x5e, 0xb9, 0xcf, 0xc7, 0xca,
508 0x35, 0xc2, 0xe5, 0x35, 0xc5, 0x68, 0x35, 0xbe, 0xb6, 0x02, 0x04, 0x4d,
509 0x51, 0xc4, 0xf2, 0xbf, 0x04, 0x53, 0x4e, 0xc8, 0xc1, 0xbe, 0x58, 0xc8,
510 0xc1, 0xc1, 0x55, 0xc8, 0xc1, 0xbb, 0x5d, 0xc5, 0x64, 0xb6, 0xd9, 0xc7,
511 0x75, 0xb8, 0xb0, 0xc3, 0x9e, 0xb5, 0x44, 0xc2, 0x0f, 0xba, 0x29, 0xc2,
512 0x0f, 0xb7, 0xa6, 0xc2, 0x0f, 0xbe, 0x58, 0x04, 0x0a, 0x00, 0x01, 0x00,
513 0x12, 0x42, 0x19, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x19,
514 0x98, 0xc6, 0x19, 0x93, 0x44, 0x19, 0xa2, 0x01, 0x17, 0x84, 0x00, 0x04,
515 0x0a, 0x01, 0x01, 0x00, 0x12, 0x42, 0x19, 0x98, 0x00, 0x00, 0x00, 0x00,
516 0x00, 0x00, 0x42, 0x19, 0x98, 0xc7, 0x26, 0x5f, 0x28, 0x96, 0xf9, 0x01,
517 0x17, 0x83, 0x00, 0x04, 0x0a, 0x02, 0x01, 0x01, 0x00, 0x0a, 0x03, 0x02,
518 0x02, 0x03, 0x00
521 // #pragma mark - PageIconView
524 class URLInputGroup::PageIconView : public BView {
525 public:
526 PageIconView()
528 BView("page icon view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
529 fIcon(NULL)
531 SetDrawingMode(B_OP_ALPHA);
532 SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
533 SetViewUIColor(B_DOCUMENT_BACKGROUND_COLOR);
536 ~PageIconView()
538 delete fIcon;
541 virtual void Draw(BRect updateRect)
543 BRect bounds(Bounds());
544 BRect iconBounds(0, 0, 15, 15);
545 iconBounds.OffsetTo(
546 floorf((bounds.left + bounds.right
547 - (iconBounds.left + iconBounds.right)) / 2 + 0.5f),
548 floorf((bounds.top + bounds.bottom
549 - (iconBounds.top + iconBounds.bottom)) / 2 + 0.5f));
550 DrawBitmap(fIcon, fIcon->Bounds(), iconBounds,
551 B_FILTER_BITMAP_BILINEAR);
554 virtual BSize MinSize()
556 return BSize(18, 18);
559 virtual BSize MaxSize()
561 return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
564 virtual BSize PreferredSize()
566 return MinSize();
569 void SetIcon(const BBitmap* icon)
571 delete fIcon;
572 if (icon)
573 fIcon = new BBitmap(icon);
574 else {
575 fIcon = new BBitmap(BRect(0, 0, 15, 15), B_RGB32);
576 BIconUtils::GetVectorIcon(kPlaceholderIcon,
577 sizeof(kPlaceholderIcon), fIcon);
579 Invalidate();
582 private:
583 BBitmap* fIcon;
587 // #pragma mark - URLInputGroup
590 URLInputGroup::URLInputGroup(BMessage* goMessage)
592 BGroupView(B_HORIZONTAL, 0.0),
593 fWindowActive(false),
594 fURLLocked(false)
596 GroupLayout()->SetInsets(2, 2, 2, 2);
598 fIconView = new PageIconView();
599 GroupLayout()->AddView(fIconView, 0.0f);
601 fTextView = new URLTextView(this);
602 AddChild(fTextView);
604 AddChild(new BSeparatorView(B_VERTICAL, B_PLAIN_BORDER));
606 // TODO: Fix in Haiku, no in-built support for archived BBitmaps from
607 // resources?
608 // fGoButton = new BitmapButton("kActionGo", NULL);
609 fGoButton = new BitmapButton(kGoBitmapBits, kGoBitmapWidth,
610 kGoBitmapHeight, kGoBitmapFormat, goMessage);
611 GroupLayout()->AddView(fGoButton, 0.0f);
613 SetFlags(Flags() | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
614 SetLowColor(ViewColor());
615 SetViewColor(fTextView->ViewColor());
617 SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
618 B_ALIGN_VERTICAL_CENTER));
623 URLInputGroup::~URLInputGroup()
628 void
629 URLInputGroup::AttachedToWindow()
631 BGroupView::AttachedToWindow();
632 fWindowActive = Window()->IsActive();
636 void
637 URLInputGroup::WindowActivated(bool active)
639 BGroupView::WindowActivated(active);
640 if (fWindowActive != active) {
641 fWindowActive = active;
642 Invalidate();
647 void
648 URLInputGroup::Draw(BRect updateRect)
650 BRect bounds(Bounds());
651 rgb_color base(LowColor());
652 uint32 flags = 0;
653 if (fWindowActive && fTextView->IsFocus())
654 flags |= BControlLook::B_FOCUSED;
655 be_control_look->DrawTextControlBorder(this, bounds, updateRect, base,
656 flags);
660 void
661 URLInputGroup::MakeFocus(bool focus)
663 // Forward this to the text view, we never accept focus ourselves.
664 fTextView->MakeFocus(focus);
668 BTextView*
669 URLInputGroup::TextView() const
671 return fTextView;
675 void
676 URLInputGroup::SetText(const char* text)
678 // Ignore setting the text, if the input is locked.
679 if (fURLLocked)
680 return;
682 if (!text || !Text() || strcmp(Text(), text) != 0) {
683 fTextView->SetUpdateAutoCompleterChoices(false);
684 fTextView->SetText(text);
685 fTextView->SetUpdateAutoCompleterChoices(true);
690 const char*
691 URLInputGroup::Text() const
693 return fTextView->Text();
697 BButton*
698 URLInputGroup::GoButton() const
700 return fGoButton;
704 void
705 URLInputGroup::SetPageIcon(const BBitmap* icon)
707 fIconView->SetIcon(icon);
711 bool
712 URLInputGroup::IsURLInputLocked() const
714 return fURLLocked;
718 void
719 URLInputGroup::LockURLInput(bool lock)
721 fURLLocked = lock;