btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / apps / cortex / RouteApp / StatusView.cpp
blob10658fcba0a5b3766c58a917d26926ad8c6739a3
1 /*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions, and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 // StatusView.cpp
34 #include "StatusView.h"
35 #include "cortex_ui.h"
36 #include "RouteAppNodeManager.h"
37 #include "TipManager.h"
39 // Application Kit
40 #include <Message.h>
41 #include <MessageRunner.h>
42 // Interface Kit
43 #include <Bitmap.h>
44 #include <Font.h>
45 #include <ScrollBar.h>
46 #include <Window.h>
47 // Support Kit
48 #include <Beep.h>
50 __USE_CORTEX_NAMESPACE
52 #include <Debug.h>
53 #define D_ALLOC(x) //PRINT(x)
54 #define D_HOOK(x) //PRINT(x)
55 #define D_MESSAGE(x) //PRINT(x)
56 #define D_OPERATION(x) //PRINT(x)
58 // -------------------------------------------------------- //
59 // *** constants
60 // -------------------------------------------------------- //
62 const bigtime_t TICK_PERIOD = 50000;
63 const bigtime_t TEXT_DECAY_DELAY = 10 * 1000 * 1000;
64 const bigtime_t TEXT_DECAY_TIME = 3 * 1000 * 1000;
66 // width: 8, height:12, color_space: B_CMAP8
67 const unsigned char ERROR_ICON_BITS [] = {
68 0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,
69 0xff,0x00,0xfa,0xfa,0x00,0xff,0xff,0xff,
70 0x00,0x3f,0x3f,0xfa,0xfa,0x00,0xff,0xff,
71 0x00,0xf9,0xf9,0x3f,0x5d,0x00,0xff,0xff,
72 0x00,0xf9,0xf9,0x5d,0x5d,0x00,0xff,0xff,
73 0x00,0xf9,0xf9,0x5d,0x5d,0x00,0xff,0xff,
74 0x00,0x00,0xf9,0x5d,0x00,0x00,0xff,0xff,
75 0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,
76 0x00,0xf9,0x00,0x00,0x5d,0x00,0xff,0xff,
77 0x00,0xf9,0xf9,0x5d,0x5d,0x00,0xff,0xff,
78 0x00,0x00,0xf9,0x5d,0x00,0x00,0x0f,0xff,
79 0xff,0xff,0x00,0x00,0x00,0x0f,0x0f,0x0f,
82 // width: 8, height:12, color_space: B_CMAP8
83 const unsigned char INFO_ICON_BITS [] = {
84 0xff,0xff,0x00,0x00,0x00,0xff,0xff,0xff,
85 0xff,0x00,0x21,0x21,0x21,0x00,0xff,0xff,
86 0xff,0x00,0x21,0x92,0x25,0x00,0xff,0xff,
87 0xff,0x00,0x21,0x25,0x25,0x00,0xff,0xff,
88 0xff,0xff,0x00,0x00,0x00,0xff,0xff,0xff,
89 0xff,0x00,0x92,0x92,0x25,0x00,0xff,0xff,
90 0xff,0x00,0x21,0x21,0x25,0x00,0xff,0xff,
91 0xff,0x00,0x21,0x21,0x25,0x00,0xff,0xff,
92 0x00,0x00,0x21,0x21,0x25,0x00,0x00,0xff,
93 0x00,0xbe,0x21,0x21,0x92,0xbe,0x25,0x00,
94 0x00,0x00,0x21,0x21,0x21,0x25,0x00,0x0f,
95 0xff,0xff,0x00,0x00,0x00,0x00,0x0f,0x0f,
98 // -------------------------------------------------------- //
99 // *** ctor/dtor
100 // -------------------------------------------------------- //
102 StatusView::StatusView(
103 BRect frame,
104 RouteAppNodeManager *manager,
105 BScrollBar *scrollBar)
106 : BStringView(frame, "StatusView", "", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM,
107 B_FRAME_EVENTS | B_WILL_DRAW),
108 m_scrollBar(scrollBar),
109 m_icon(0),
110 m_opacity(1.0),
111 m_clock(0),
112 m_dragging(false),
113 m_backBitmap(0),
114 m_backView(0),
115 m_dirty(true),
116 m_manager(manager) {
117 D_ALLOC(("StatusView::StatusView()\n"));
119 SetViewColor(B_TRANSPARENT_COLOR);
120 SetFont(be_plain_font);
122 allocBackBitmap(frame.Width(), frame.Height());
125 StatusView::~StatusView() {
126 D_ALLOC(("StatusView::~ParameterContainerView()\n"));
128 // get the tip manager instance and reset
129 TipManager *manager = TipManager::Instance();
130 manager->removeAll(this);
132 delete m_clock;
134 freeBackBitmap();
137 // -------------------------------------------------------- //
138 // *** BScrollView impl
139 // -------------------------------------------------------- //
141 void StatusView::AttachedToWindow() {
142 D_HOOK(("StatusView::AttachedToWindow()\n"));
144 if (m_manager) {
145 m_manager->setLogTarget(BMessenger(this, Window()));
148 allocBackBitmap(Bounds().Width(), Bounds().Height());
151 void StatusView::Draw(
152 BRect updateRect) {
153 D_HOOK(("StatusView::Draw()\n"));
155 if(!m_backView) {
156 drawInto(this, updateRect);
157 } else {
158 if(m_dirty) {
159 m_backBitmap->Lock();
160 drawInto(m_backView, updateRect);
161 m_backView->Sync();
162 m_backBitmap->Unlock();
163 m_dirty = false;
166 SetDrawingMode(B_OP_COPY);
167 DrawBitmap(m_backBitmap, updateRect, updateRect);
171 void StatusView::FrameResized(
172 float width,
173 float height) {
174 D_HOOK(("StatusView::FrameResized()\n"));
176 allocBackBitmap(width, height);
178 // get the tip manager instance and reset
179 TipManager *manager = TipManager::Instance();
180 manager->removeAll(this);
182 // re-truncate the string if necessary
183 BString text = m_fullText;
184 if (be_plain_font->StringWidth(text.String()) > Bounds().Width() - 25.0) {
185 be_plain_font->TruncateString(&text, B_TRUNCATE_END,
186 Bounds().Width() - 25.0);
187 manager->setTip(m_fullText.String(), this);
189 BStringView::SetText(text.String());
191 float minWidth, maxWidth, minHeight, maxHeight;
192 Window()->GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight);
193 minWidth = width + 6 * B_V_SCROLL_BAR_WIDTH;
194 Window()->SetSizeLimits(minWidth, maxWidth, minHeight, maxHeight);
197 void StatusView::MessageReceived(
198 BMessage *message) {
199 D_MESSAGE(("StatusView::MessageReceived()\n"));
201 switch (message->what) {
202 case 'Tick':
203 fadeTick();
204 break;
206 case RouteAppNodeManager::M_LOG: {
207 D_MESSAGE((" -> RouteAppNodeManager::M_LOG\n"));
209 BString title;
210 if (message->FindString("title", &title) != B_OK) {
211 return;
213 BString details, line;
214 for (int32 i = 0; message->FindString("line", i, &line) == B_OK; i++) {
215 if (details.CountChars() > 0) {
216 details << "\n";
218 details << line;
220 status_t error = B_OK;
221 message->FindInt32("error", &error);
222 setMessage(title, details, error);
223 break;
225 default: {
226 BStringView::MessageReceived(message);
231 void StatusView::MouseDown(
232 BPoint point) {
233 D_HOOK(("StatusView::MouseDown()\n"));
235 int32 buttons;
236 if (Window()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK) {
237 buttons = B_PRIMARY_MOUSE_BUTTON;
240 if (buttons == B_PRIMARY_MOUSE_BUTTON) {
241 // drag rect
242 BRect dragRect(Bounds());
243 dragRect.left = dragRect.right - 10.0;
244 if (dragRect.Contains(point)) {
245 // resize
246 m_dragging = true;
247 SetMouseEventMask(B_POINTER_EVENTS,
248 B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
253 void StatusView::MouseMoved(
254 BPoint point,
255 uint32 transit,
256 const BMessage *message) {
257 D_HOOK(("StatusView::MouseMoved()\n"));
259 if (m_dragging) {
260 float x = point.x - (Bounds().right - 5.0);
261 if ((Bounds().Width() + x) <= 16.0) {
262 return;
264 if (m_scrollBar
265 && ((m_scrollBar->Bounds().Width() - x) <= (6 * B_V_SCROLL_BAR_WIDTH))) {
266 return;
268 ResizeBy(x, 0.0);
269 BRect r(Bounds());
270 r.left = r.right - 5.0;
271 if (x > 0)
272 r.left -= x;
273 m_dirty = true;
274 Invalidate(r);
275 if (m_scrollBar) {
276 m_scrollBar->ResizeBy(-x, 0.0);
277 m_scrollBar->MoveBy(x, 0.0);
282 void StatusView::MouseUp(
283 BPoint point) {
284 D_HOOK(("StatusView::MouseUp()\n"));
286 m_dragging = false;
289 // -------------------------------------------------------- //
290 // *** internal operations
291 // -------------------------------------------------------- //
293 void
294 StatusView::drawInto(BView *v, BRect updateRect)
296 BRect r(Bounds());
297 D_OPERATION(("StatusView::drawInto(%.1f, %.1f)\n", r.Width(), r.Height()));
299 // draw border (minus right edge, which the scrollbar draws)
300 v->SetDrawingMode(B_OP_COPY);
301 v->BeginLineArray(8);
302 v->AddLine(r.LeftTop(), r.RightTop(), M_MED_GRAY_COLOR);
303 BPoint rtop = r.RightTop();
304 rtop.y++;
305 v->AddLine(rtop, r.RightBottom(), tint_color(M_MED_GRAY_COLOR, B_LIGHTEN_1_TINT));
306 v->AddLine(r.RightBottom(), r.LeftBottom(), M_MED_GRAY_COLOR);
307 v->AddLine(r.LeftBottom(), r.LeftTop(), M_MED_GRAY_COLOR);
308 r.InsetBy(1.0, 1.0);
309 v->AddLine(r.LeftTop(), r.RightTop(), M_LIGHT_GRAY_COLOR);
310 rtop.y++;
311 rtop.x--;
312 v->AddLine(rtop, r.RightBottom(), M_GRAY_COLOR);
313 v->AddLine(r.RightBottom(), r.LeftBottom(), tint_color(M_MED_GRAY_COLOR, B_LIGHTEN_1_TINT));
314 v->AddLine(r.LeftBottom(), r.LeftTop(), M_LIGHT_GRAY_COLOR);
315 v->EndLineArray();
316 r.InsetBy(1.0, 1.0);
317 v->SetLowColor(M_GRAY_COLOR);
318 v->FillRect(r, B_SOLID_LOW);
320 r.InsetBy(2.0, 0.0);
321 v->SetDrawingMode(B_OP_ALPHA);
322 v->SetHighColor(0, 0, 0, uchar(255 * m_opacity));
324 // draw icon
325 if (m_icon) {
326 v->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
327 BPoint p = r.LeftTop();
328 p.y--;
329 v->DrawBitmap(m_icon, p);
332 // draw text
333 r.left += 10.0;
334 font_height fh;
335 be_plain_font->GetHeight(&fh);
336 r.bottom = Bounds().bottom - fh.descent
337 - (Bounds().Height() - fh.ascent - fh.descent) / 2;
338 v->MovePenTo(r.LeftBottom());
339 v->DrawString(Text());
341 // draw resize dragger
342 v->SetDrawingMode(B_OP_OVER);
343 r = Bounds();
344 r.right -= 2.0;
345 r.left = r.right - 2.0;
346 r.InsetBy(0.0, 3.0);
347 r.top += 1.0;
348 for (int32 i = 0; i < r.IntegerHeight(); i += 3) {
349 BPoint p = r.LeftTop() + BPoint(0.0, i);
350 v->SetHighColor(M_MED_GRAY_COLOR);
351 v->StrokeLine(p, p, B_SOLID_HIGH);
352 p += BPoint(1.0, 1.0);
353 v->SetHighColor(M_WHITE_COLOR);
354 v->StrokeLine(p, p, B_SOLID_HIGH);
360 void StatusView::setMessage(
361 BString &title,
362 BString &details,
363 status_t error) {
364 D_OPERATION(("StatusView::setMessage(%s)\n", title.String()));
366 // get the tip manager instance and reset
367 TipManager *manager = TipManager::Instance();
368 manager->removeAll(this);
370 // append error string
371 if (error) {
372 title << " (" << strerror(error) << ")";
375 // truncate if necessary
376 bool truncated = false;
377 m_fullText = title;
378 if (be_plain_font->StringWidth(title.String()) > Bounds().Width() - 25.0) {
379 be_plain_font->TruncateString(&title, B_TRUNCATE_END,
380 Bounds().Width() - 25.0);
381 truncated = true;
383 BStringView::SetText(title.String());
385 if (truncated || details.CountChars() > 0) {
386 BString tip = m_fullText;
387 if (details.CountChars() > 0) {
388 tip << "\n" << details;
390 manager->setTip(tip.String(), this);
393 if (error) {
394 beep();
395 // set icon
396 if (m_icon) {
397 delete m_icon;
398 m_icon = 0;
400 BRect iconRect(0.0, 0.0, 7.0, 11.0);
401 m_icon = new BBitmap(iconRect, B_CMAP8);
402 m_icon->SetBits(ERROR_ICON_BITS, 96, 0, B_CMAP8);
404 else {
405 // set icon
406 if (m_icon) {
407 delete m_icon;
408 m_icon = 0;
410 BRect iconRect(0.0, 0.0, 7.0, 11.0);
411 m_icon = new BBitmap(iconRect, B_CMAP8);
412 m_icon->SetBits(INFO_ICON_BITS, 96, 0, B_CMAP8);
414 m_dirty = true;
415 startFade();
416 Invalidate();
419 void StatusView::setErrorMessage(
420 BString text,
421 bool error) {
422 D_OPERATION(("StatusView::setErrorMessage(%s)\n",
423 text.String()));
425 // get the tip manager instance and reset
426 TipManager *manager = TipManager::Instance();
427 manager->removeAll(this);
429 // truncate if necessary
430 m_fullText = text;
431 if (be_plain_font->StringWidth(text.String()) > Bounds().Width() - 25.0) {
432 be_plain_font->TruncateString(&text, B_TRUNCATE_END,
433 Bounds().Width() - 25.0);
434 manager->setTip(m_fullText.String(), this);
436 BStringView::SetText(text.String());
438 if (error) {
439 beep();
440 // set icon
441 if (m_icon) {
442 delete m_icon;
443 m_icon = 0;
445 BRect iconRect(0.0, 0.0, 7.0, 11.0);
446 m_icon = new BBitmap(iconRect, B_CMAP8);
447 m_icon->SetBits(ERROR_ICON_BITS, 96, 0, B_CMAP8);
449 else {
450 // set icon
451 if (m_icon) {
452 delete m_icon;
453 m_icon = 0;
455 BRect iconRect(0.0, 0.0, 7.0, 11.0);
456 m_icon = new BBitmap(iconRect, B_CMAP8);
457 m_icon->SetBits(INFO_ICON_BITS, 96, 0, B_CMAP8);
459 m_dirty = true;
460 startFade();
461 Invalidate();
464 void StatusView::startFade() {
465 D_OPERATION(("StatusView::startFade()\n"));
467 m_opacity = 1.0;
468 m_decayDelay = TEXT_DECAY_DELAY;
469 if(!m_clock) {
470 m_clock = new BMessageRunner(
471 BMessenger(this),
472 new BMessage('Tick'),
473 TICK_PERIOD);
477 void StatusView::fadeTick() {
478 D_HOOK(("StatusView::fadeTick()\n"));
480 if (m_opacity > 0.0) {
481 if(m_decayDelay > 0) {
482 m_decayDelay -= TICK_PERIOD;
483 return;
486 float steps = static_cast<float>(TEXT_DECAY_TIME)
487 / static_cast<float>(TICK_PERIOD);
488 m_opacity -= (1.0 / steps);
489 if (m_opacity < 0.001) {
490 m_opacity = 0.0;
492 m_dirty = true;
493 Invalidate();
495 else if (m_clock) {
496 delete m_clock;
497 m_clock = 0;
499 // get the tip manager instance and reset
500 TipManager *manager = TipManager::Instance();
501 manager->removeAll(this);
505 void StatusView::allocBackBitmap(float width, float height) {
506 D_OPERATION(("StatusView::allocBackBitmap(%.1f, %.1f)\n", width, height));
508 // sanity check
509 if(width <= 0.0 || height <= 0.0)
510 return;
512 if(m_backBitmap) {
513 // see if the bitmap needs to be expanded
514 BRect b = m_backBitmap->Bounds();
515 if(b.Width() >= width && b.Height() >= height)
516 return;
518 // it does; clean up:
519 freeBackBitmap();
522 BRect b(0.0, 0.0, width, height);
523 m_backBitmap = new BBitmap(b, B_RGB32, true);
524 if(!m_backBitmap) {
525 D_OPERATION(("StatusView::allocBackBitmap(): failed to allocate\n"));
526 return;
529 m_backView = new BView(b, 0, B_FOLLOW_NONE, B_WILL_DRAW);
530 m_backBitmap->AddChild(m_backView);
531 m_dirty = true;
534 void StatusView::freeBackBitmap() {
535 if(m_backBitmap) {
536 delete m_backBitmap;
537 m_backBitmap = 0;
538 m_backView = 0;
543 // END -- ParameterContainerView.cpp --