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