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 in 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 // defines the status area drawn in the bottom left corner of a Tracker window 36 37 #include <Application.h> 38 39 #include "AutoLock.h" 40 #include "Bitmaps.h" 41 #include "CountView.h" 42 #include "ContainerWindow.h" 43 #include "DirMenu.h" 44 #include "PoseView.h" 45 46 BCountView::BCountView(BRect bounds, BPoseView* view) 47 : BView(bounds, "CountVw", B_FOLLOW_LEFT + B_FOLLOW_BOTTOM, 48 B_PULSE_NEEDED | B_WILL_DRAW), 49 fLastCount(-1), 50 fPoseView(view), 51 fShowingBarberPole(false), 52 fBarberPoleMap(NULL), 53 fLastBarberPoleOffset(5), 54 fStartSpinningAfter(0), 55 fTypeAheadString("") 56 57 { 58 GetTrackerResources()->GetBitmapResource(B_MESSAGE_TYPE, kResBarberPoleBitmap, 59 &fBarberPoleMap); 60 } 61 62 BCountView::~BCountView() 63 { 64 delete fBarberPoleMap; 65 } 66 67 void 68 BCountView::TrySpinningBarberPole() 69 { 70 if (!fShowingBarberPole) 71 return; 72 73 if (fStartSpinningAfter && system_time() < fStartSpinningAfter) 74 return; 75 76 if (fStartSpinningAfter) { 77 fStartSpinningAfter = 0; 78 Invalidate(BarberPoleOuterRect()); 79 } else 80 Invalidate(BarberPoleInnerRect()); 81 } 82 83 void 84 BCountView::Pulse() 85 { 86 TrySpinningBarberPole(); 87 } 88 89 void 90 BCountView::EndBarberPole() 91 { 92 if (!fShowingBarberPole) 93 return; 94 95 fShowingBarberPole = false; 96 Invalidate(); 97 } 98 99 const bigtime_t kBarberPoleDelay = 500000; 100 101 void 102 BCountView::StartBarberPole() 103 { 104 AutoLock<BWindow> lock(Window()); 105 if (fShowingBarberPole) 106 return; 107 108 fShowingBarberPole = true; 109 fStartSpinningAfter = system_time() + kBarberPoleDelay; 110 // wait a bit before showing the barber pole 111 } 112 113 BRect 114 BCountView::BarberPoleInnerRect() const 115 { 116 BRect result = Bounds(); 117 result.InsetBy(3, 4); 118 result.left = result.right - 7; 119 result.bottom = result.top + 7; 120 return result; 121 } 122 123 BRect 124 BCountView::BarberPoleOuterRect() const 125 { 126 BRect result(BarberPoleInnerRect()); 127 result.InsetBy(-1, -1); 128 return result; 129 } 130 131 BRect 132 BCountView::TextInvalRect() const 133 { 134 BRect result = Bounds(); 135 result.InsetBy(4, 2); 136 result.right -= 10; 137 138 return result; 139 } 140 141 void 142 BCountView::CheckCount() 143 { 144 // invalidate the count text area if necessary 145 if (fLastCount != fPoseView->CountItems()) { 146 fLastCount = fPoseView->CountItems(); 147 Invalidate(TextInvalRect()); 148 } 149 // invalidate barber pole area if necessary 150 TrySpinningBarberPole(); 151 } 152 153 void 154 BCountView::Draw(BRect) 155 { 156 BRect bounds(Bounds()); 157 BRect barberPoleRect; 158 BString itemString; 159 if (!IsTypingAhead()) { 160 if (fLastCount == 0) 161 itemString << "no items"; 162 else if (fLastCount == 1) 163 itemString << "1 item"; 164 else 165 itemString << fLastCount << " items"; 166 } else 167 itemString << TypeAhead(); 168 169 170 BString string(itemString); 171 BRect textRect(TextInvalRect()); 172 173 if (fShowingBarberPole && !fStartSpinningAfter) { 174 barberPoleRect = BarberPoleOuterRect(); 175 TruncateString(&string, B_TRUNCATE_END, textRect.Width()); 176 } 177 178 if (IsTypingAhead()) 179 // use a muted gray for the typeahead 180 SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_4_TINT)); 181 else 182 SetHighColor(0, 0, 0); 183 MovePenTo(textRect.LeftBottom()); 184 DrawString(string.String()); 185 186 bounds.top++; 187 188 rgb_color light = tint_color(ViewColor(), B_LIGHTEN_MAX_TINT); 189 rgb_color shadow = tint_color(ViewColor(), B_DARKEN_2_TINT); 190 rgb_color lightShadow = tint_color(ViewColor(), B_DARKEN_1_TINT); 191 192 BeginLineArray(fShowingBarberPole && !fStartSpinningAfter ? 9 : 5); 193 AddLine(bounds.LeftTop(), bounds.RightTop(), light); 194 AddLine(bounds.LeftTop(), bounds.LeftBottom(), light); 195 bounds.top--; 196 197 AddLine(bounds.LeftTop(), bounds.RightTop(), shadow); 198 AddLine(BPoint(bounds.right, bounds.top + 2), bounds.RightBottom(), lightShadow); 199 AddLine(bounds.LeftBottom(), bounds.RightBottom(), lightShadow); 200 201 if (!fShowingBarberPole || fStartSpinningAfter) { 202 EndLineArray(); 203 return; 204 } 205 206 AddLine(barberPoleRect.LeftTop(), barberPoleRect.RightTop(), shadow); 207 AddLine(barberPoleRect.LeftTop(), barberPoleRect.LeftBottom(), shadow); 208 AddLine(barberPoleRect.LeftBottom(), barberPoleRect.RightBottom(), light); 209 AddLine(barberPoleRect.RightBottom(), barberPoleRect.RightTop(), light); 210 EndLineArray(); 211 212 barberPoleRect.InsetBy(1, 1); 213 214 BRect destRect(fBarberPoleMap ? fBarberPoleMap->Bounds() : BRect(0, 0, 0, 0)); 215 destRect.OffsetTo(barberPoleRect.LeftTop() - BPoint(0, fLastBarberPoleOffset)); 216 fLastBarberPoleOffset -= 1; 217 if (fLastBarberPoleOffset < 0) 218 fLastBarberPoleOffset = 5; 219 220 BRegion region; 221 region.Set(BarberPoleInnerRect()); 222 ConstrainClippingRegion(®ion); 223 224 if (fBarberPoleMap) 225 DrawBitmap(fBarberPoleMap, destRect); 226 } 227 228 void 229 BCountView::MouseDown(BPoint) 230 { 231 BContainerWindow *window = dynamic_cast<BContainerWindow *>(Window()); 232 window->Activate(); 233 window->UpdateIfNeeded(); 234 235 if (fPoseView->IsFilePanel() || !fPoseView->TargetModel()) 236 return; 237 238 if (!window->TargetModel()->IsRoot()) { 239 BDirMenu *menu = new BDirMenu(NULL, B_REFS_RECEIVED); 240 BEntry entry; 241 if (entry.SetTo(window->TargetModel()->EntryRef()) == B_OK) 242 menu->Populate(&entry, Window(), false, false, true, false, true); 243 else 244 menu->Populate(NULL, Window(), false, false, true, false, true); 245 246 menu->SetTargetForItems(be_app); 247 BPoint pop_pt = Bounds().LeftBottom(); 248 pop_pt.y += 3; 249 ConvertToScreen(&pop_pt); 250 BRect mouse_rect(Bounds()); 251 ConvertToScreen(&mouse_rect); 252 menu->Go(pop_pt, true, true, mouse_rect); 253 delete menu; 254 } 255 } 256 257 void 258 BCountView::AttachedToWindow() 259 { 260 SetFont(be_plain_font); 261 SetFontSize(9); 262 263 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 264 SetLowColor(ViewColor()); 265 266 CheckCount(); 267 } 268 269 void 270 BCountView::SetTypeAhead(const char *string) 271 { 272 fTypeAheadString = string; 273 Invalidate(); 274 } 275 276 const char * 277 BCountView::TypeAhead() const 278 { 279 return fTypeAheadString.String(); 280 } 281 282 bool 283 BCountView::IsTypingAhead() const 284 { 285 return fTypeAheadString.Length() != 0; 286 } 287