1/* 2 * Copyright (C) 2010 Stephan A��mus <superstippi@gmx.de> 3 * Copyright (C) 2010 Adrien Destugues <pulkomandy@pulkomandy.ath.cx> 4 * 5 * Distributed under the terms of the MIT licence. 6 */ 7 8#include "ApplicationView.h" 9 10#include <stdio.h> 11 12#include <Alert.h> 13#include <Bitmap.h> 14#include <Button.h> 15#include <Clipboard.h> 16#include <Directory.h> 17#include <Entry.h> 18#include <FindDirectory.h> 19#include <GroupLayoutBuilder.h> 20#include <MenuItem.h> 21#include <NodeInfo.h> 22#include <NodeMonitor.h> 23#include <PopUpMenu.h> 24#include <Roster.h> 25#include <SpaceLayoutItem.h> 26#include <StatusBar.h> 27#include <StringView.h> 28 29 30class IconView : public BView { 31public: 32 IconView(const BEntry& entry) 33 : 34 BView("Download icon", B_WILL_DRAW), 35 fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32), 36 fDimmedIcon(false) 37 { 38 SetDrawingMode(B_OP_OVER); 39 SetTo(entry); 40 } 41 42 IconView() 43 : 44 BView("Download icon", B_WILL_DRAW), 45 fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32), 46 fDimmedIcon(false) 47 { 48 SetDrawingMode(B_OP_OVER); 49 memset(fIconBitmap.Bits(), 0, fIconBitmap.BitsLength()); 50 } 51 52 IconView(const BMessage* archive) 53 : 54 BView("Download icon", B_WILL_DRAW), 55 fIconBitmap((BMessage*)archive), 56 fDimmedIcon(true) 57 { 58 SetDrawingMode(B_OP_OVER); 59 } 60 61 void SetTo(const BEntry& entry) 62 { 63 BNode node(&entry); 64 BNodeInfo info(&node); 65 info.GetTrackerIcon(&fIconBitmap, B_LARGE_ICON); 66 Invalidate(); 67 } 68 69 void SetIconDimmed(bool iconDimmed) 70 { 71 if (fDimmedIcon != iconDimmed) { 72 fDimmedIcon = iconDimmed; 73 Invalidate(); 74 } 75 } 76 77 bool IsIconDimmed() const 78 { 79 return fDimmedIcon; 80 } 81 82 status_t SaveSettings(BMessage* archive) 83 { 84 return fIconBitmap.Archive(archive); 85 } 86 87 virtual void AttachedToWindow() 88 { 89 SetViewColor(Parent()->ViewColor()); 90 } 91 92 virtual void Draw(BRect updateRect) 93 { 94 if (fDimmedIcon) { 95 SetDrawingMode(B_OP_ALPHA); 96 SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); 97 SetHighColor(0, 0, 0, 100); 98 } 99 DrawBitmapAsync(&fIconBitmap); 100 } 101 102 virtual BSize MinSize() 103 { 104 return BSize(fIconBitmap.Bounds().Width(), fIconBitmap.Bounds().Height()); 105 } 106 107 virtual BSize PreferredSize() 108 { 109 return MinSize(); 110 } 111 112 virtual BSize MaxSize() 113 { 114 return MinSize(); 115 } 116 117private: 118 BBitmap fIconBitmap; 119 bool fDimmedIcon; 120}; 121 122 123class SmallButton : public BButton { 124public: 125 SmallButton(const char* label, BMessage* message = NULL) 126 : 127 BButton(label, message) 128 { 129 BFont font; 130 GetFont(&font); 131 float size = ceilf(font.Size() * 0.8); 132 font.SetSize(max_c(8, size)); 133 SetFont(&font, B_FONT_SIZE); 134 } 135}; 136 137 138// #pragma mark - ApplicationView 139 140 141ApplicationView::ApplicationView(const char* name, const char* icon, 142 const char* description) 143 : 144 BGroupView(B_HORIZONTAL, 8) 145{ 146 Init(NULL); 147 148 fNameView->SetText(name); 149 fInfoView->SetText(description); 150} 151 152 153ApplicationView::ApplicationView(const BMessage* archive) 154 : 155 BGroupView(B_HORIZONTAL, 8) 156{ 157 Init(archive); 158 BString temp; 159 archive->FindString("appname",&temp); 160 fNameView->SetText(temp); 161 archive->FindString("appdesc",&temp); 162 float ver = 0.0; 163 archive->FindFloat("appver", ver); 164 int size = 0; 165 archive->FindInt32("appsize", size); 166 temp << " Version: " << ver << " Size: " << size; 167 fInfoView->SetText(temp); 168} 169 170 171bool 172ApplicationView::Init(const BMessage* archive) 173{ 174 SetViewColor(245, 245, 245); 175 SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); 176 177 if (archive) { 178 fIconView = new IconView(archive); 179 } else 180 fIconView = new IconView(); 181 182 if (archive) { 183 fTopButton = new SmallButton("Info", new BMessage('NADA')); 184 fBottomButton = new SmallButton("Install", new BMessage('NADA')); 185 } 186 187 fInfoView = new BStringView("info view", ""); 188 fNameView = new BStringView("name view", ""); 189 190 BGroupLayout* layout = GroupLayout(); 191 layout->SetInsets(8, 5, 5, 6); 192 layout->AddView(fIconView); 193 BView* verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3) 194 .Add(fNameView) 195 .Add(fInfoView) 196 .TopView() 197 ; 198 verticalGroup->SetViewColor(ViewColor()); 199 layout->AddView(verticalGroup); 200 if (fTopButton && fBottomButton) { 201 verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3) 202 .Add(fTopButton) 203 .Add(fBottomButton) 204 .TopView() 205 ; 206 } 207 verticalGroup->SetViewColor(ViewColor()); 208 layout->AddView(verticalGroup); 209 210 BFont font; 211 fInfoView->GetFont(&font); 212 float fontSize = font.Size() * 0.8f; 213 font.SetSize(max_c(8.0f, fontSize)); 214 fInfoView->SetFont(&font, B_FONT_SIZE); 215 fInfoView->SetHighColor(tint_color(fInfoView->LowColor(), 216 B_DARKEN_4_TINT)); 217 fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 218 219 fNameView->GetFont(&font); 220 font.SetSize(font.Size() * 2.0f); 221 fNameView->SetFont(&font, B_FONT_SIZE); 222 fNameView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 223 224 return true; 225} 226 227 228void 229ApplicationView::AttachedToWindow() 230{ 231 if (fTopButton) 232 fTopButton->SetTarget(this); 233 if (fBottomButton) 234 fBottomButton->SetTarget(this); 235} 236 237 238void 239ApplicationView::AllAttached() 240{ 241 SetViewColor(B_TRANSPARENT_COLOR); 242 SetLowColor(245, 245, 245); 243 SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT)); 244} 245 246 247void 248ApplicationView::Draw(BRect updateRect) 249{ 250 BRect bounds(Bounds()); 251 bounds.bottom--; 252 FillRect(bounds, B_SOLID_LOW); 253 bounds.bottom++; 254 StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); 255} 256 257 258void 259ApplicationView::MessageReceived(BMessage* message) 260{ 261 switch (message->what) { 262 case B_NODE_MONITOR: 263 { 264 int32 opCode; 265 if (message->FindInt32("opcode", &opCode) != B_OK) 266 break; 267 switch (opCode) { 268 case B_ENTRY_MOVED: 269 { 270 // Follow the entry to the new location 271 dev_t device; 272 ino_t directory; 273 const char* name; 274 if (message->FindInt32("device", 275 reinterpret_cast<int32*>(&device)) != B_OK 276 || message->FindInt64("to directory", 277 reinterpret_cast<int64*>(&directory)) != B_OK 278 || message->FindString("name", &name) != B_OK 279 || strlen(name) == 0) { 280 break; 281 } 282 283 Window()->PostMessage(SAVE_SETTINGS); 284 break; 285 } 286 case B_ATTR_CHANGED: 287 { 288 fIconView->SetIconDimmed(false); 289 break; 290 } 291 } 292 break; 293 } 294 295 default: 296 BGroupView::MessageReceived(message); 297 } 298} 299 300 301void 302ApplicationView::ShowContextMenu(BPoint screenWhere) 303{ 304 screenWhere += BPoint(2, 2); 305 306 BPopUpMenu* contextMenu = new BPopUpMenu("download context"); 307 BMenuItem* copyURL = new BMenuItem("Copy URL to clipboard", 308 new BMessage('NADA')); 309 contextMenu->AddItem(copyURL); 310 BMenuItem* openFolder = new BMenuItem("Open containing folder", 311 new BMessage('NADA')); 312 contextMenu->AddItem(openFolder); 313 314 contextMenu->SetTargetForItems(this); 315 contextMenu->Go(screenWhere, true, true, true); 316} 317 318