2 * Copyright 2006-2009, Stephan Aßmus <superstippi@gmx.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
10 #include <Application.h>
12 #include <GroupLayout.h>
15 #include <PopUpMenu.h>
18 #include <SpaceLayoutItem.h>
20 #include "LaunchButton.h"
21 #include "MainWindow.h"
24 #undef B_TRANSLATION_CONTEXT
25 #define B_TRANSLATION_CONTEXT "LaunchBox"
28 static bigtime_t sActivationDelay
= 40000;
29 static const uint32 kIconSizes
[] = { 16, 20, 24, 32, 40, 48, 64 };
33 MSG_TOGGLE_LAYOUT
= 'tgll',
34 MSG_SET_ICON_SIZE
= 'stis',
35 MSG_SET_IGNORE_DOUBLECLICK
= 'strd'
39 PadView::PadView(const char* name
)
40 : BView(name
, B_WILL_DRAW
| B_FULL_UPDATE_ON_RESIZE
, NULL
),
43 fButtonLayout(new BGroupLayout(B_VERTICAL
, 4)),
44 fIconSize(DEFAULT_ICON_SIZE
)
46 SetViewColor(B_TRANSPARENT_32_BIT
);
47 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR
));
48 get_click_speed(&sActivationDelay
);
50 fButtonLayout
->SetInsets(2, 7, 2, 2);
51 SetLayout(fButtonLayout
);
61 PadView::Draw(BRect updateRect
)
63 rgb_color background
= LowColor();
64 rgb_color light
= tint_color(background
, B_LIGHTEN_MAX_TINT
);
65 rgb_color shadow
= tint_color(background
, B_DARKEN_2_TINT
);
68 AddLine(BPoint(r
.left
, r
.bottom
), BPoint(r
.left
, r
.top
), light
);
69 AddLine(BPoint(r
.left
+ 1.0, r
.top
), BPoint(r
.right
, r
.top
), light
);
70 AddLine(BPoint(r
.right
, r
.top
+ 1.0), BPoint(r
.right
, r
.bottom
), shadow
);
71 AddLine(BPoint(r
.right
- 1.0, r
.bottom
), BPoint(r
.left
+ 1.0, r
.bottom
), shadow
);
74 StrokeRect(r
, B_SOLID_LOW
);
77 BPoint dot
= r
.LeftTop();
82 if (Orientation() == B_VERTICAL
) {
83 current
= (int32
)dot
.x
;
84 stop
= (int32
)r
.right
;
85 offset
= BPoint(0, 1);
89 current
= (int32
)dot
.y
;
90 stop
= (int32
)r
.bottom
;
91 offset
= BPoint(1, 0);
96 while (current
<= stop
) {
102 } else if (num
== 2) {
111 StrokeLine(dot
, dot
, B_SOLID_HIGH
);
114 StrokeLine(dot
, dot
, B_SOLID_HIGH
);
116 StrokeLine(dot
, dot
, B_SOLID_LOW
);
119 StrokeLine(dot
, dot
, B_SOLID_HIGH
);
122 StrokeLine(dot
, dot
, B_SOLID_HIGH
);
128 FillRect(r
, B_SOLID_LOW
);
133 PadView::MessageReceived(BMessage
* message
)
135 switch (message
->what
) {
136 case MSG_TOGGLE_LAYOUT
:
137 if (fButtonLayout
->Orientation() == B_HORIZONTAL
) {
138 fButtonLayout
->SetInsets(2, 7, 2, 2);
139 fButtonLayout
->SetOrientation(B_VERTICAL
);
141 fButtonLayout
->SetInsets(7, 2, 2, 2);
142 fButtonLayout
->SetOrientation(B_HORIZONTAL
);
146 case MSG_SET_ICON_SIZE
:
148 if (message
->FindInt32("size", (int32
*)&size
) == B_OK
)
152 case MSG_SET_IGNORE_DOUBLECLICK
:
153 SetIgnoreDoubleClick(!IgnoreDoubleClick());
157 BView::MessageReceived(message
);
164 PadView::MouseDown(BPoint where
)
166 BWindow
* window
= Window();
171 GetClippingRegion(®ion
);
172 if (!region
.Contains(where
))
176 for (int32 i
= 0; BView
* child
= ChildAt(i
); i
++) {
177 if (child
->Frame().Contains(where
)) {
185 BMessage
* message
= window
->CurrentMessage();
190 message
->FindInt32("buttons", (int32
*)&buttons
);
191 if (buttons
& B_SECONDARY_MOUSE_BUTTON
) {
195 if (r
.Contains(where
)) {
198 // sends the window to the back
199 window
->Activate(false);
202 if (system_time() - fClickTime
< sActivationDelay
) {
203 window
->Minimize(true);
207 fDragOffset
= ConvertToScreen(where
) - window
->Frame().LeftTop();
209 SetMouseEventMask(B_POINTER_EVENTS
, B_LOCK_WINDOW_FOCUS
);
210 fClickTime
= system_time();
217 PadView::MouseUp(BPoint where
)
219 if (BWindow
* window
= Window()) {
221 window
->CurrentMessage()->FindInt32("buttons", (int32
*)&buttons
);
222 if (buttons
& B_PRIMARY_MOUSE_BUTTON
223 && system_time() - fClickTime
< sActivationDelay
224 && window
->IsActive())
232 PadView::MouseMoved(BPoint where
, uint32 transit
, const BMessage
* dragMessage
)
234 MainWindow
* window
= dynamic_cast<MainWindow
*>(Window());
239 window
->MoveTo(ConvertToScreen(where
) - fDragOffset
);
240 } else if (window
->AutoRaise()) {
241 where
= ConvertToScreen(where
);
242 BScreen
screen(window
);
243 BRect frame
= screen
.Frame();
244 BRect windowFrame
= window
->Frame();
245 if (where
.x
== frame
.left
|| where
.x
== frame
.right
246 || where
.y
== frame
.top
|| where
.y
== frame
.bottom
) {
247 BPoint position
= window
->ScreenPosition();
249 if (fabs(0.5 - position
.x
) > fabs(0.5 - position
.y
)) {
250 // left or right border
251 if (where
.y
>= windowFrame
.top
252 && where
.y
<= windowFrame
.bottom
) {
253 if (position
.x
< 0.5 && where
.x
== frame
.left
)
255 else if (position
.x
> 0.5 && where
.x
== frame
.right
)
259 // top or bottom border
260 if (where
.x
>= windowFrame
.left
&& where
.x
<= windowFrame
.right
) {
261 if (position
.y
< 0.5 && where
.y
== frame
.top
)
263 else if (position
.y
> 0.5 && where
.y
== frame
.bottom
)
275 PadView::AddButton(LaunchButton
* button
, LaunchButton
* beforeButton
)
277 button
->SetIconSize(fIconSize
);
280 fButtonLayout
->AddView(fButtonLayout
->IndexOfView(beforeButton
), button
);
282 fButtonLayout
->AddView(button
);
284 _NotifySettingsChanged();
289 PadView::RemoveButton(LaunchButton
* button
)
291 bool result
= fButtonLayout
->RemoveView(button
);
293 _NotifySettingsChanged();
299 PadView::ButtonAt(int32 index
) const
301 BLayoutItem
* item
= fButtonLayout
->ItemAt(index
);
304 return dynamic_cast<LaunchButton
*>(item
->View());
309 PadView::DisplayMenu(BPoint where
, LaunchButton
* button
) const
311 MainWindow
* window
= dynamic_cast<MainWindow
*>(Window());
315 LaunchButton
* nearestButton
= button
;
316 if (!nearestButton
) {
317 // find the nearest button
318 for (int32 i
= 0; (nearestButton
= ButtonAt(i
)); i
++) {
319 if (nearestButton
->Frame().top
> where
.y
)
323 BPopUpMenu
* menu
= new BPopUpMenu(B_TRANSLATE("launch popup"), false, false);
325 BMessage
* message
= new BMessage(MSG_ADD_SLOT
);
326 message
->AddPointer("be:source", (void*)nearestButton
);
327 BMenuItem
* item
= new BMenuItem(B_TRANSLATE("Add button here"), message
);
328 item
->SetTarget(window
);
333 message
= new BMessage(MSG_CLEAR_SLOT
);
334 message
->AddPointer("be:source", (void*)button
);
335 item
= new BMenuItem(B_TRANSLATE("Clear button"), message
);
336 item
->SetTarget(window
);
339 message
= new BMessage(MSG_REMOVE_SLOT
);
340 message
->AddPointer("be:source", (void*)button
);
341 item
= new BMenuItem(B_TRANSLATE("Remove button"), message
);
342 item
->SetTarget(window
);
344 // Open containing folder button
345 if (button
->Ref() != NULL
) {
346 message
= new BMessage(MSG_OPEN_CONTAINING_FOLDER
);
347 message
->AddPointer("be:source", (void*)button
);
348 item
= new BMenuItem(B_TRANSLATE("Open containing folder"), message
);
349 item
->SetTarget(window
);
352 // set button description
354 message
= new BMessage(MSG_SET_DESCRIPTION
);
355 message
->AddPointer("be:source", (void*)button
);
356 item
= new BMenuItem(B_TRANSLATE("Set description" B_UTF8_ELLIPSIS
),
358 item
->SetTarget(window
);
362 menu
->AddSeparatorItem();
364 BMenu
* settingsM
= new BMenu(B_TRANSLATE("Settings"));
365 settingsM
->SetFont(be_plain_font
);
367 const char* toggleLayoutLabel
;
368 if (fButtonLayout
->Orientation() == B_HORIZONTAL
)
369 toggleLayoutLabel
= B_TRANSLATE("Vertical layout");
371 toggleLayoutLabel
= B_TRANSLATE("Horizontal layout");
372 item
= new BMenuItem(toggleLayoutLabel
, new BMessage(MSG_TOGGLE_LAYOUT
));
373 item
->SetTarget(this);
374 settingsM
->AddItem(item
);
376 BMenu
* iconSizeM
= new BMenu(B_TRANSLATE("Icon size"));
377 for (uint32 i
= 0; i
< sizeof(kIconSizes
) / sizeof(uint32
); i
++) {
378 uint32 iconSize
= kIconSizes
[i
];
379 message
= new BMessage(MSG_SET_ICON_SIZE
);
380 message
->AddInt32("size", iconSize
);
382 label
<< iconSize
<< " x " << iconSize
;
383 item
= new BMenuItem(label
.String(), message
);
384 item
->SetTarget(this);
385 item
->SetMarked(IconSize() == iconSize
);
386 iconSizeM
->AddItem(item
);
388 settingsM
->AddItem(iconSizeM
);
390 item
= new BMenuItem(B_TRANSLATE("Ignore double-click"),
391 new BMessage(MSG_SET_IGNORE_DOUBLECLICK
));
392 item
->SetTarget(this);
393 item
->SetMarked(IgnoreDoubleClick());
394 settingsM
->AddItem(item
);
396 uint32 what
= window
->Look() == B_BORDERED_WINDOW_LOOK
? MSG_SHOW_BORDER
: MSG_HIDE_BORDER
;
397 item
= new BMenuItem(B_TRANSLATE("Show window border"), new BMessage(what
));
398 item
->SetTarget(window
);
399 item
->SetMarked(what
== MSG_HIDE_BORDER
);
400 settingsM
->AddItem(item
);
402 item
= new BMenuItem(B_TRANSLATE("Auto-raise"), new BMessage(MSG_TOGGLE_AUTORAISE
));
403 item
->SetTarget(window
);
404 item
->SetMarked(window
->AutoRaise());
405 settingsM
->AddItem(item
);
407 item
= new BMenuItem(B_TRANSLATE("Show on all workspaces"), new BMessage(MSG_SHOW_ON_ALL_WORKSPACES
));
408 item
->SetTarget(window
);
409 item
->SetMarked(window
->ShowOnAllWorkspaces());
410 settingsM
->AddItem(item
);
412 menu
->AddItem(settingsM
);
414 menu
->AddSeparatorItem();
417 BMenu
* padM
= new BMenu(B_TRANSLATE("Pad"));
418 padM
->SetFont(be_plain_font
);
420 item
= new BMenuItem(B_TRANSLATE("New"), new BMessage(MSG_ADD_WINDOW
));
421 item
->SetTarget(be_app
);
424 item
= new BMenuItem(B_TRANSLATE("Clone"), new BMessage(MSG_ADD_WINDOW
));
425 item
->SetTarget(window
);
427 padM
->AddSeparatorItem();
429 item
= new BMenuItem(B_TRANSLATE("Close"), new BMessage(B_QUIT_REQUESTED
));
430 item
->SetTarget(window
);
434 BMenu
* appM
= new BMenu(B_TRANSLATE_SYSTEM_NAME("LaunchBox"));
435 appM
->SetFont(be_plain_font
);
437 item
= new BMenuItem(B_TRANSLATE("Quit"), new BMessage(B_QUIT_REQUESTED
));
438 item
->SetTarget(be_app
);
442 menu
->SetAsyncAutoDestruct(true);
443 menu
->SetFont(be_plain_font
);
444 where
= ConvertToScreen(where
);
445 BRect
mouseRect(where
, where
);
446 mouseRect
.InsetBy(-4.0, -4.0);
447 menu
->Go(where
, true, false, mouseRect
, true);
452 PadView::SetOrientation(enum orientation orientation
)
454 if (orientation
== B_VERTICAL
) {
455 fButtonLayout
->SetInsets(2, 7, 2, 2);
456 fButtonLayout
->SetOrientation(B_VERTICAL
);
458 fButtonLayout
->SetInsets(7, 2, 2, 2);
459 fButtonLayout
->SetOrientation(B_HORIZONTAL
);
461 _NotifySettingsChanged();
466 PadView::Orientation() const
468 return fButtonLayout
->Orientation();
473 PadView::SetIconSize(uint32 size
)
475 if (size
== fIconSize
)
480 for (int32 i
= 0; LaunchButton
* button
= ButtonAt(i
); i
++)
481 button
->SetIconSize(fIconSize
);
483 _NotifySettingsChanged();
488 PadView::IconSize() const
495 PadView::SetIgnoreDoubleClick(bool refuse
)
497 LaunchButton::SetIgnoreDoubleClick(refuse
);
499 _NotifySettingsChanged();
504 PadView::IgnoreDoubleClick() const
506 return LaunchButton::IgnoreDoubleClick();
511 PadView::_NotifySettingsChanged()
513 be_app
->PostMessage(MSG_SETTINGS_CHANGED
);