xref: /haiku/src/kits/tracker/DraggableContainerIcon.cpp (revision 1978089f7cec856677e46204e992c7273d70b9af)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal including
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28 
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34 
35 
36 #include "DraggableContainerIcon.h"
37 
38 #include <algorithm>
39 
40 #include <ControlLook.h>
41 #include <IconUtils.h>
42 #include <MenuItem.h>
43 #include <Region.h>
44 
45 #include "ContainerWindow.h"
46 #include "IconCache.h"
47 #include "Model.h"
48 
49 
50 // amount to move the mouse over for before a drag starts
51 const float kDragSlop = 3.0f;
52 
53 
54 DraggableContainerIcon::DraggableContainerIcon(BSize iconSize)
55 	:
56 	BView("DraggableContainerIcon", B_WILL_DRAW),
57 	fIconSize(iconSize),
58 	fDragButton(0),
59 	fDragStarted(false)
60 {
61 	SetExplicitMinSize(BSize(iconSize.Width() + 5, iconSize.Height()));
62 	SetExplicitMaxSize(BSize(iconSize.Width() + 5, B_SIZE_UNSET));
63 }
64 
65 
66 void
67 DraggableContainerIcon::MouseDown(BPoint where)
68 {
69 	// we only like container windows
70 	BContainerWindow* window = dynamic_cast<BContainerWindow*>(Window());
71 	ThrowOnAssert(window != NULL);
72 
73 	// we don't like the Trash icon (because it cannot be moved)
74 	if (window->IsTrash() || window->IsPrintersDir())
75 		return;
76 
77 	uint32 buttons;
78 	window->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
79 
80 	if (IconCache::sIconCache->IconHitTest(where, window->TargetModel(),
81 			kNormalIcon, fIconSize)) {
82 		// The click hit the icon, initiate a drag
83 		fDragButton = buttons
84 			& (B_PRIMARY_MOUSE_BUTTON | B_SECONDARY_MOUSE_BUTTON);
85 		fDragStarted = false;
86 		fClickPoint = where;
87 	} else
88 		fDragButton = 0;
89 
90 	if (!fDragButton)
91 		Window()->Activate(true);
92 }
93 
94 
95 void
96 DraggableContainerIcon::MouseUp(BPoint)
97 {
98 	if (!fDragStarted)
99 		Window()->Activate(true);
100 
101 	fDragButton = 0;
102 	fDragStarted = false;
103 }
104 
105 
106 void
107 DraggableContainerIcon::MouseMoved(BPoint where, uint32, const BMessage*)
108 {
109 	if (fDragButton == 0 || fDragStarted
110 		|| (abs((int32)(where.x - fClickPoint.x)) <= kDragSlop
111 			&& abs((int32)(where.y - fClickPoint.y)) <= kDragSlop))
112 		return;
113 
114 	BContainerWindow* window = static_cast<BContainerWindow*>(Window());
115 		// we can only get here in a BContainerWindow
116 	Model* model = window->TargetModel();
117 
118 	// Find the required height
119 	BFont font;
120 	GetFont(&font);
121 
122 	font_height fontHeight;
123 	font.GetHeight(&fontHeight);
124 	float height = ceilf(fontHeight.ascent + fontHeight.descent
125 		+ fontHeight.leading + 2 + Bounds().Height() + 8);
126 
127 	BRect rect(0, 0, std::max(Bounds().Width(),
128 		font.StringWidth(model->Name()) + 4), height);
129 	BBitmap* dragBitmap = new BBitmap(rect, B_RGBA32, true);
130 
131 	dragBitmap->Lock();
132 	BView* view = new BView(dragBitmap->Bounds(), "", B_FOLLOW_NONE, 0);
133 	dragBitmap->AddChild(view);
134 	view->SetOrigin(0, 0);
135 	BRect clipRect(view->Bounds());
136 	BRegion newClip;
137 	newClip.Set(clipRect);
138 	view->ConstrainClippingRegion(&newClip);
139 
140 	// Transparent draw magic
141 	view->SetHighColor(0, 0, 0, 0);
142 	view->FillRect(view->Bounds());
143 	view->SetDrawingMode(B_OP_ALPHA);
144 
145 	rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
146 	textColor.alpha = 128;
147 		// set the level of transparency by value
148 	view->SetHighColor(textColor);
149 	view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
150 
151 	// Draw the icon
152 	float hIconOffset = (rect.Width() - Bounds().Width()) / 2;
153 	IconCache::sIconCache->Draw(model, view, BPoint(hIconOffset, 0),
154 		kNormalIcon, fIconSize, true);
155 
156 	// See if we need to truncate the string
157 	BString nameString = model->Name();
158 	if (view->StringWidth(model->Name()) > rect.Width()) {
159 		view->TruncateString(&nameString, B_TRUNCATE_MIDDLE,
160 			rect.Width() - 5);
161 	}
162 
163 	// Draw the label
164 	float leftText = (view->StringWidth(nameString.String())
165 		- Bounds().Width()) / 2;
166 	view->MovePenTo(BPoint(hIconOffset - leftText + 2, Bounds().Height()
167 		+ (fontHeight.ascent + 2)));
168 	view->DrawString(nameString.String());
169 
170 	view->Sync();
171 	dragBitmap->Unlock();
172 
173 	BMessage message(B_SIMPLE_DATA);
174 	message.AddRef("refs", model->EntryRef());
175 	message.AddPoint("click_pt", fClickPoint);
176 
177 	BPoint tmpLoc;
178 	uint32 button;
179 	GetMouse(&tmpLoc, &button);
180 	if (button)
181 		message.AddInt32("buttons", (int32)button);
182 
183 	if ((button & B_PRIMARY_MOUSE_BUTTON) != 0) {
184 		// add an action specifier to the message, so that it is not copied
185 		message.AddInt32("be:actions", (modifiers() & B_OPTION_KEY) != 0
186 			? B_COPY_TARGET : B_MOVE_TARGET);
187 	}
188 
189 	fDragStarted = true;
190 	fDragButton = 0;
191 
192 	DragMessage(&message, dragBitmap, B_OP_ALPHA,
193 		BPoint(fClickPoint.x + hIconOffset, fClickPoint.y), this);
194 }
195 
196 
197 void
198 DraggableContainerIcon::Draw(BRect updateRect)
199 {
200 	BContainerWindow* window = dynamic_cast<BContainerWindow*>(Window());
201 	ThrowOnAssert(window != NULL);
202 
203 	BRect rect(Bounds());
204 	rgb_color base = ui_color(B_MENU_BACKGROUND_COLOR);
205 	be_control_look->DrawBorder(this, rect, updateRect, base, B_PLAIN_BORDER,
206 		0, BControlLook::B_BOTTOM_BORDER);
207 	be_control_look->DrawMenuBarBackground(this, rect, updateRect, base, 0,
208 		BControlLook::B_ALL_BORDERS & ~BControlLook::B_LEFT_BORDER);
209 
210 	// Draw the icon, straddling the border
211 	SetDrawingMode(B_OP_ALPHA);
212 	SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
213 	float iconOffsetX = (Bounds().Width() - fIconSize.Width()) / 2;
214 	float iconOffsetY = (Bounds().Height() - fIconSize.Height()) / 2;
215 	IconCache::sIconCache->Draw(window->TargetModel(), this,
216 		BPoint(iconOffsetX, iconOffsetY), kNormalIcon, fIconSize, true);
217 }
218 
219