btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / kits / tracker / Pose.cpp
blob49d7cb3dab1490f9ccf0413514e94f5141c3d13b
1 /*
2 Open Tracker License
4 Terms and Conditions
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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:
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.
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.
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.
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.
36 #include <stdlib.h>
37 #include <string.h>
39 #include <Debug.h>
40 #include <NodeMonitor.h>
41 #include <Volume.h>
42 #include <fs_info.h>
44 #include "Attributes.h"
45 #include "Commands.h"
46 #include "FSClipboard.h"
47 #include "IconCache.h"
48 #include "Pose.h"
49 #include "PoseView.h"
52 int32
53 CalcFreeSpace(BVolume* volume)
55 off_t capacity = volume->Capacity();
56 if (capacity == 0)
57 return 100;
59 int32 percent
60 = static_cast<int32>(volume->FreeBytes() / (capacity / 100));
62 // warn below 5% of free space
63 if (percent < 5)
64 return -2 - percent;
65 return percent;
69 // SymLink handling:
70 // symlink pose uses the resolved model to retrieve the icon, if not broken
71 // everything else, like the attributes, etc. is retrieved directly from the
72 // symlink itself
73 BPose::BPose(Model* model, BPoseView* view, uint32 clipboardMode,
74 bool selected)
76 fModel(model),
77 fWidgetList(4, false),
78 fClipboardMode(clipboardMode),
79 fPercent(-1),
80 fSelectionTime(0),
81 fIsSelected(selected),
82 fHasLocation(false),
83 fNeedsSaveLocation(false),
84 fListModeInited(false),
85 fWasAutoPlaced(false),
86 fBrokenSymLink(false),
87 fBackgroundClean(false)
89 CreateWidgets(view);
91 if (model->IsVolume()) {
92 fs_info info;
93 dev_t device = model->NodeRef()->device;
94 BVolume* volume = new BVolume(device);
95 if (volume->InitCheck() == B_OK
96 && fs_stat_dev(device, &info) == B_OK) {
97 // Philosophy here:
98 // Bars go on all read/write volumes
99 // Exceptions: Not on CDDA
100 if (strcmp(info.fsh_name,"cdda") != 0
101 && !volume->IsReadOnly()) {
102 // The volume is ok and we want space bars on it
103 gPeriodicUpdatePoses.AddPose(this, view,
104 _PeriodicUpdateCallback, volume);
105 if (TrackerSettings().ShowVolumeSpaceBar())
106 fPercent = CalcFreeSpace(volume);
107 } else
108 delete volume;
109 } else
110 delete volume;
115 BPose::~BPose()
117 if (fModel->IsVolume()) {
118 // we might be registered for periodic updates
119 BVolume* volume = NULL;
120 if (gPeriodicUpdatePoses.RemovePose(this, (void**)&volume))
121 delete volume;
123 int32 count = fWidgetList.CountItems();
124 for (int32 i = 0; i < count; i++)
125 delete fWidgetList.ItemAt(i);
127 delete fModel;
131 void
132 BPose::CreateWidgets(BPoseView* poseView)
134 for (int32 index = 0; ; index++) {
135 BColumn* column = poseView->ColumnAt(index);
136 if (column == NULL)
137 break;
139 fWidgetList.AddItem(new BTextWidget(fModel, column, poseView));
144 BTextWidget*
145 BPose::AddWidget(BPoseView* poseView, BColumn* column)
147 BModelOpener opener(fModel);
148 if (fModel->InitCheck() != B_OK)
149 return NULL;
151 BTextWidget* widget = new BTextWidget(fModel, column, poseView);
152 fWidgetList.AddItem(widget);
154 return widget;
158 BTextWidget*
159 BPose::AddWidget(BPoseView* poseView, BColumn* column,
160 ModelNodeLazyOpener &opener)
162 opener.OpenNode();
163 if (fModel->InitCheck() != B_OK)
164 return NULL;
166 BTextWidget* widget = new BTextWidget(fModel, column, poseView);
167 fWidgetList.AddItem(widget);
169 return widget;
173 void
174 BPose::RemoveWidget(BPoseView*, BColumn* column)
176 int32 index;
177 BTextWidget* widget = WidgetFor(column->AttrHash(), &index);
178 if (widget != NULL)
179 delete fWidgetList.RemoveItemAt(index);
183 void
184 BPose::Commit(bool saveChanges, BPoint loc, BPoseView* poseView,
185 int32 poseIndex)
187 int32 count = fWidgetList.CountItems();
188 for (int32 index = 0; index < count; index++) {
189 BTextWidget* widget = fWidgetList.ItemAt(index);
190 if (widget != NULL && widget->IsActive()) {
191 widget->StopEdit(saveChanges, loc, poseView, this, poseIndex);
192 break;
198 inline bool
199 OneMouseUp(BTextWidget* widget, BPose* pose, BPoseView* poseView,
200 BColumn* column, BPoint poseLoc, BPoint where)
202 BRect rect;
203 if (poseView->ViewMode() == kListMode)
204 rect = widget->CalcClickRect(poseLoc, column, poseView);
205 else
206 rect = widget->CalcClickRect(pose->Location(poseView), NULL, poseView);
208 if (rect.Contains(where)) {
209 widget->MouseUp(rect, poseView, pose, where);
210 return true;
213 return false;
217 void
218 BPose::MouseUp(BPoint poseLoc, BPoseView* poseView, BPoint where, int32)
220 WhileEachTextWidget(this, poseView, OneMouseUp, poseLoc, where);
224 inline void
225 OneCheckAndUpdate(BTextWidget* widget, BPose*, BPoseView* poseView,
226 BColumn* column, BPoint poseLoc)
228 widget->CheckAndUpdate(poseLoc, column, poseView, true);
232 void
233 BPose::UpdateAllWidgets(int32, BPoint poseLoc, BPoseView* poseView)
235 if (poseView->ViewMode() != kListMode)
236 poseLoc = Location(poseView);
238 ASSERT(fModel->IsNodeOpen());
239 EachTextWidget(this, poseView, OneCheckAndUpdate, poseLoc);
243 void
244 BPose::UpdateWidgetAndModel(Model* resolvedModel, const char* attrName,
245 uint32 attrType, int32, BPoint poseLoc, BPoseView* poseView, bool visible)
247 if (poseView->ViewMode() != kListMode)
248 poseLoc = Location(poseView);
250 ASSERT(resolvedModel == NULL || resolvedModel->IsNodeOpen());
252 if (attrName != NULL) {
253 // pick up new attributes and find out if icon needs updating
254 if (resolvedModel->AttrChanged(attrName) && visible)
255 UpdateIcon(poseLoc, poseView);
257 // ToDo: the following code is wrong, because this sort of hashing
258 // may overlap and we get aliasing
259 uint32 attrHash = AttrHashString(attrName, attrType);
260 BTextWidget* widget = WidgetFor(attrHash);
261 if (widget != NULL) {
262 BColumn* column = poseView->ColumnFor(attrHash);
263 if (column != NULL)
264 widget->CheckAndUpdate(poseLoc, column, poseView, visible);
265 } else if (attrType == 0) {
266 // attribute got likely removed, so let's search the
267 // column for the matching attribute name
268 int32 count = fWidgetList.CountItems();
269 for (int32 i = 0; i < count; i++) {
270 BTextWidget* widget = fWidgetList.ItemAt(i);
271 BColumn* column = poseView->ColumnFor(widget->AttrHash());
272 if (column != NULL
273 && strcmp(column->AttrName(), attrName) == 0) {
274 widget->CheckAndUpdate(poseLoc, column, poseView, visible);
275 break;
279 } else {
280 // no attr name means check all widgets for stat info changes
282 // pick up stat changes
283 if (resolvedModel && resolvedModel->StatChanged()) {
284 if (resolvedModel->InitCheck() != B_OK)
285 return;
287 if (visible)
288 UpdateIcon(poseLoc, poseView);
291 // distribute stat changes
292 for (int32 index = 0; ; index++) {
293 BColumn* column = poseView->ColumnAt(index);
294 if (column == NULL)
295 break;
297 if (column->StatField()) {
298 BTextWidget* widget = WidgetFor(column->AttrHash());
299 if (widget != NULL)
300 widget->CheckAndUpdate(poseLoc, column, poseView, visible);
307 bool
308 BPose::_PeriodicUpdateCallback(BPose* pose, void* cookie)
310 return pose->UpdateVolumeSpaceBar((BVolume*)cookie);
314 bool
315 BPose::UpdateVolumeSpaceBar(BVolume* volume)
317 bool enabled = TrackerSettings().ShowVolumeSpaceBar();
318 if (!enabled) {
319 if (fPercent == -1)
320 return false;
322 fPercent = -1;
323 return true;
326 int32 percent = CalcFreeSpace(volume);
327 if (fPercent != percent) {
328 if (percent > 100)
329 fPercent = 100;
330 else
331 fPercent = percent;
333 return true;
336 return false;
340 void
341 BPose::UpdateIcon(BPoint poseLoc, BPoseView* poseView)
343 IconCache::sIconCache->IconChanged(ResolvedModel());
345 int32 iconSize = poseView->IconSizeInt();
347 BRect rect;
348 if (poseView->ViewMode() == kListMode) {
349 rect = CalcRect(poseLoc, poseView);
350 rect.left += kListOffset;
351 rect.right = rect.left + iconSize;
352 rect.top = rect.bottom - iconSize;
353 } else {
354 BPoint location = Location(poseView);
355 rect.left = location.x;
356 rect.top = location.y;
357 rect.right = rect.left + iconSize;
358 rect.bottom = rect.top + iconSize;
361 poseView->Invalidate(rect);
365 void
366 BPose::UpdateBrokenSymLink(BPoint poseLoc, BPoseView* poseView)
368 ASSERT(TargetModel()->IsSymLink());
369 ASSERT(TargetModel()->LinkTo() == NULL);
370 if (!TargetModel()->IsSymLink() || TargetModel()->LinkTo() != NULL)
371 return;
373 UpdateIcon(poseLoc, poseView);
377 void
378 BPose::UpdateWasBrokenSymlink(BPoint poseLoc, BPoseView* poseView)
380 if (!fModel->IsSymLink())
381 return;
383 if (fModel->LinkTo() != NULL) {
384 BEntry entry(fModel->EntryRef(), true);
385 if (entry.InitCheck() != B_OK) {
386 watch_node(fModel->LinkTo()->NodeRef(), B_STOP_WATCHING, poseView);
387 fModel->SetLinkTo(NULL);
388 UpdateIcon(poseLoc, poseView);
390 return;
393 poseView->CreateSymlinkPoseTarget(fModel);
394 UpdateIcon(poseLoc, poseView);
395 if (fModel->LinkTo() != NULL)
396 fModel->LinkTo()->CloseNode();
400 void
401 BPose::EditFirstWidget(BPoint poseLoc, BPoseView* poseView)
403 // find first editable widget
404 BColumn* column;
405 for (int32 i = 0; (column = poseView->ColumnAt(i)) != NULL; i++) {
406 BTextWidget* widget = WidgetFor(column->AttrHash());
408 if (widget != NULL && widget->IsEditable()) {
409 BRect bounds;
410 // ToDo:
411 // fold the three StartEdit code sequences into a cover call
412 if (poseView->ViewMode() == kListMode)
413 bounds = widget->CalcRect(poseLoc, column, poseView);
414 else
415 bounds = widget->CalcRect(Location(poseView), NULL, poseView);
417 widget->StartEdit(bounds, poseView, this);
418 break;
424 void
425 BPose::EditPreviousNextWidgetCommon(BPoseView* poseView, bool next)
427 bool found = false;
428 int32 delta = next ? 1 : -1;
429 for (int32 index = next ? 0 : poseView->CountColumns() - 1; ;
430 index += delta) {
431 BColumn* column = poseView->ColumnAt(index);
432 if (column == NULL) {
433 // out of columns
434 break;
437 BTextWidget* widget = WidgetFor(column->AttrHash());
438 if (widget == NULL) {
439 // no widget for this column, next
440 continue;
443 if (widget->IsActive()) {
444 poseView->CommitActivePose();
445 found = true;
446 continue;
449 if (found && column->Editable()) {
450 BRect bounds;
451 if (poseView->ViewMode() == kListMode) {
452 int32 poseIndex = poseView->IndexOfPose(this);
453 BPoint poseLoc(0, poseIndex* poseView->ListElemHeight());
454 bounds = widget->CalcRect(poseLoc, column, poseView);
455 } else
456 bounds = widget->CalcRect(Location(poseView), NULL, poseView);
458 widget->StartEdit(bounds, poseView, this);
459 break;
465 void
466 BPose::EditNextWidget(BPoseView* poseView)
468 EditPreviousNextWidgetCommon(poseView, true);
472 void
473 BPose::EditPreviousWidget(BPoseView* poseView)
475 EditPreviousNextWidgetCommon(poseView, false);
479 bool
480 BPose::PointInPose(const BPoseView* poseView, BPoint where) const
482 ASSERT(poseView->ViewMode() != kListMode);
484 BPoint location = Location(poseView);
486 if (poseView->ViewMode() == kIconMode) {
487 // check icon rect, then actual icon pixel
488 BRect rect(location, location);
489 rect.right += poseView->IconSizeInt() - 1;
490 rect.bottom += poseView->IconSizeInt() - 1;
492 if (rect.Contains(where)) {
493 return IconCache::sIconCache->IconHitTest(where - location,
494 ResolvedModel(), kNormalIcon, poseView->IconSize());
497 BTextWidget* widget = WidgetFor(poseView->FirstColumn()->AttrHash());
498 if (widget) {
499 float textWidth = ceilf(widget->TextWidth(poseView) + 1);
500 rect.left += (poseView->IconSizeInt() - textWidth) / 2;
501 rect.right = rect.left + textWidth;
504 rect.top = location.y + poseView->IconSizeInt();
505 rect.bottom = rect.top + poseView->FontHeight();
507 return rect.Contains(where);
510 // MINI_ICON_MODE rect calc
511 BRect rect(location, location);
512 rect.right += B_MINI_ICON + kMiniIconSeparator;
513 rect.bottom += poseView->IconPoseHeight();
514 BTextWidget* widget = WidgetFor(poseView->FirstColumn()->AttrHash());
515 if (widget != NULL)
516 rect.right += ceil(widget->TextWidth(poseView) + 1);
518 return rect.Contains(where);
522 bool
523 BPose::PointInPose(BPoint loc, const BPoseView* poseView, BPoint where,
524 BTextWidget** hitWidget) const
526 if (hitWidget != NULL)
527 *hitWidget = NULL;
529 // check intersection with icon
530 BRect rect = _IconRect(poseView, loc);
531 if (rect.Contains(where))
532 return true;
534 for (int32 index = 0; ; index++) {
535 BColumn* column = poseView->ColumnAt(index);
536 if (column == NULL)
537 break;
539 BTextWidget* widget = WidgetFor(column->AttrHash());
540 if (widget != NULL
541 && widget->CalcClickRect(loc, column, poseView).Contains(where)) {
542 if (hitWidget != NULL)
543 *hitWidget = widget;
545 return true;
549 return false;
553 void
554 BPose::Draw(BRect rect, const BRect& updateRect, BPoseView* poseView,
555 BView* drawView, bool fullDraw, BPoint offset, bool selected)
557 // If the background wasn't cleared and Draw() is not called after
558 // having edited a name or similar (with fullDraw)
559 if (!fBackgroundClean && !fullDraw) {
560 fBackgroundClean = true;
561 poseView->Invalidate(rect);
562 return;
563 } else
564 fBackgroundClean = false;
566 bool directDraw = (drawView == poseView);
567 bool windowActive = poseView->Window()->IsActive();
568 bool showSelectionWhenInactive = poseView->fShowSelectionWhenInactive;
569 bool isDrawingSelectionRect = poseView->fIsDrawingSelectionRect;
571 ModelNodeLazyOpener modelOpener(fModel);
573 if (poseView->ViewMode() == kListMode) {
574 BRect iconRect = _IconRect(poseView, rect.LeftTop());
575 if (updateRect.Intersects(iconRect)) {
576 iconRect.OffsetBy(offset);
577 DrawIcon(iconRect.LeftTop(), drawView, poseView->IconSize(),
578 directDraw, !windowActive && !showSelectionWhenInactive);
581 // draw text
582 int32 columnsToDraw = 1;
583 if (fullDraw)
584 columnsToDraw = poseView->CountColumns();
586 for (int32 index = 0; index < columnsToDraw; index++) {
587 BColumn* column = poseView->ColumnAt(index);
588 if (column == NULL)
589 break;
591 // if widget doesn't exist, create it
592 BTextWidget* widget = WidgetFor(column, poseView, modelOpener);
594 if (widget != NULL && widget->IsVisible()) {
595 BRect widgetRect(widget->ColumnRect(rect.LeftTop(), column,
596 poseView));
598 if (updateRect.Intersects(widgetRect)) {
599 BRect widgetTextRect(widget->CalcRect(rect.LeftTop(),
600 column, poseView));
602 bool selectDuringDraw = directDraw && selected
603 && windowActive;
605 if (index == 0 && selectDuringDraw) {
606 // draw with dark background to select text
607 drawView->PushState();
608 drawView->SetLowColor(0, 0, 0);
611 if (index == 0) {
612 widget->Draw(widgetRect, widgetTextRect,
613 column->Width(), poseView, drawView, selected,
614 fClipboardMode, offset, directDraw);
615 } else {
616 widget->Draw(widgetTextRect, widgetTextRect,
617 column->Width(), poseView, drawView, false,
618 fClipboardMode, offset, directDraw);
621 if (index == 0 && selectDuringDraw)
622 drawView->PopState();
623 else if (index == 0 && selected) {
624 if (windowActive || isDrawingSelectionRect) {
625 widgetTextRect.OffsetBy(offset);
626 drawView->InvertRect(widgetTextRect);
627 } else if (!windowActive
628 && showSelectionWhenInactive) {
629 widgetTextRect.OffsetBy(offset);
630 drawView->PushState();
631 drawView->SetDrawingMode(B_OP_BLEND);
632 drawView->SetHighColor(128, 128, 128, 255);
633 drawView->FillRect(widgetTextRect);
634 drawView->PopState();
640 } else {
641 // draw in icon mode
642 BPoint location(Location(poseView));
643 BPoint iconOrigin(location);
644 iconOrigin += offset;
646 DrawIcon(iconOrigin, drawView, poseView->IconSize(), directDraw,
647 !windowActive && !showSelectionWhenInactive);
649 BColumn* column = poseView->FirstColumn();
650 if (column == NULL)
651 return;
653 BTextWidget* widget = WidgetFor(column, poseView, modelOpener);
654 if (widget == NULL || !widget->IsVisible())
655 return;
657 rect = widget->CalcRect(location, NULL, poseView);
659 bool selectDuringDraw = directDraw && selected
660 && (poseView->IsDesktopWindow() || windowActive);
662 if (selectDuringDraw) {
663 // draw with dark background to select text
664 drawView->PushState();
665 drawView->SetLowColor(0, 0, 0);
668 widget->Draw(rect, rect, rect.Width(), poseView, drawView,
669 selected, fClipboardMode, offset, directDraw);
671 if (selectDuringDraw)
672 drawView->PopState();
673 else if (selected && directDraw) {
674 if (windowActive || isDrawingSelectionRect) {
675 rect.OffsetBy(offset);
676 drawView->InvertRect(rect);
677 } else if (!windowActive && showSelectionWhenInactive) {
678 drawView->PushState();
679 drawView->SetDrawingMode(B_OP_BLEND);
680 drawView->SetHighColor(128, 128, 128, 255);
681 drawView->FillRect(rect);
682 drawView->PopState();
689 void
690 BPose::DeselectWithoutErasingBackground(BRect, BPoseView* poseView)
692 ASSERT(poseView->ViewMode() != kListMode);
693 ASSERT(!IsSelected());
695 BPoint location(Location(poseView));
697 // draw icon directly
698 if (fPercent == -1)
699 DrawIcon(location, poseView, poseView->IconSize(), true);
700 else
701 UpdateIcon(location, poseView);
703 BColumn* column = poseView->FirstColumn();
704 if (column == NULL)
705 return;
707 BTextWidget* widget = WidgetFor(column->AttrHash());
708 if (widget == NULL || !widget->IsVisible())
709 return;
711 // just invalidate the background, don't draw anything
712 poseView->Invalidate(widget->CalcRect(location, NULL, poseView));
716 void
717 BPose::MoveTo(BPoint point, BPoseView* poseView, bool invalidate)
719 point.x = floorf(point.x);
720 point.y = floorf(point.y);
722 BRect oldBounds;
724 BPoint oldLocation = Location(poseView);
726 ASSERT(poseView->ViewMode() != kListMode);
727 if (point == oldLocation || poseView->ViewMode() == kListMode)
728 return;
730 if (invalidate)
731 oldBounds = CalcRect(poseView);
733 // might need to move a text view if we're active
734 if (poseView->ActivePose() == this) {
735 BView* border_view = poseView->FindView("BorderView");
736 if (border_view) {
737 border_view->MoveBy(point.x - oldLocation.x,
738 point.y - oldLocation.y);
742 float scale = 1.0;
743 if (poseView->ViewMode() == kIconMode) {
744 scale = poseView->IconSize() / 32.0;
746 fLocation.x = point.x / scale;
747 fLocation.y = point.y / scale;
749 fHasLocation = true;
750 fNeedsSaveLocation = true;
752 if (invalidate) {
753 poseView->Invalidate(oldBounds);
754 poseView->Invalidate(CalcRect(poseView));
759 BTextWidget*
760 BPose::ActiveWidget() const
762 for (int32 i = fWidgetList.CountItems(); i-- > 0;) {
763 BTextWidget* widget = fWidgetList.ItemAt(i);
764 if (widget->IsActive())
765 return widget;
768 return NULL;
772 BTextWidget*
773 BPose::WidgetFor(uint32 attr, int32* index) const
775 int32 count = fWidgetList.CountItems();
776 for (int32 i = 0; i < count; i++) {
777 BTextWidget* widget = fWidgetList.ItemAt(i);
778 if (widget->AttrHash() == attr) {
779 if (index != NULL)
780 *index = i;
782 return widget;
786 return NULL;
790 BTextWidget*
791 BPose::WidgetFor(BColumn* column, BPoseView* poseView,
792 ModelNodeLazyOpener &opener, int32* index)
794 BTextWidget* widget = WidgetFor(column->AttrHash(), index);
795 if (widget == NULL)
796 widget = AddWidget(poseView, column, opener);
798 return widget;
802 // the following method is deprecated
803 bool
804 BPose::TestLargeIconPixel(BPoint point) const
806 return IconCache::sIconCache->IconHitTest(point, ResolvedModel(),
807 kNormalIcon, B_LARGE_ICON);
811 void
812 BPose::DrawIcon(BPoint where, BView* view, icon_size which, bool direct,
813 bool drawUnselected)
815 if (fClipboardMode == kMoveSelectionTo) {
816 view->SetDrawingMode(B_OP_ALPHA);
817 view->SetHighColor(0, 0, 0, 64);
818 // set the level of transparency
819 view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
820 } else if (direct)
821 view->SetDrawingMode(B_OP_OVER);
823 IconCache::sIconCache->Draw(ResolvedModel(), view, where,
824 fIsSelected && !drawUnselected ? kSelectedIcon : kNormalIcon, which,
825 true);
827 if (fPercent != -1)
828 DrawBar(where, view, which);
832 void
833 BPose::DrawBar(BPoint where, BView* view, icon_size which)
835 view->PushState();
837 int32 size = which - 1;
838 int32 yOffset;
839 int32 barWidth = (int32)(7.0f / 32.0f * (float)which);
840 if (barWidth < 4) {
841 barWidth = 4;
842 yOffset = 0;
843 } else
844 yOffset = 2;
845 int32 barHeight = size - 4 - 2 * yOffset;
847 // the black shadowed line
848 view->SetHighColor(32, 32, 32, 92);
849 view->MovePenTo(BPoint(where.x + size, where.y + 1 + yOffset));
850 view->StrokeLine(BPoint(where.x + size, where.y + size - yOffset));
851 view->StrokeLine(BPoint(where.x + size - barWidth + 1,
852 where.y + size - yOffset));
854 view->SetDrawingMode(B_OP_ALPHA);
856 // the gray frame
857 view->SetHighColor(76, 76, 76, 192);
858 BRect rect(where.x + size - barWidth,where.y + yOffset,
859 where.x + size - 1,where.y + size - 1 - yOffset);
860 view->StrokeRect(rect);
862 // calculate bar height
863 int32 percent = fPercent > -1 ? fPercent : -2 - fPercent;
864 int32 barPos = int32(barHeight * percent / 100.0);
865 if (barPos < 0)
866 barPos = 0;
867 else if (barPos > barHeight)
868 barPos = barHeight;
870 // the free space bar
871 view->SetHighColor(TrackerSettings().FreeSpaceColor());
873 rect.InsetBy(1,1);
874 BRect bar(rect);
875 bar.bottom = bar.top + barPos - 1;
876 if (barPos > 0)
877 view->FillRect(bar);
879 // the used space bar
880 bar.top = bar.bottom + 1;
881 bar.bottom = rect.bottom;
882 view->SetHighColor(fPercent < -1
883 ? TrackerSettings().WarningSpaceColor()
884 : TrackerSettings().UsedSpaceColor());
885 view->FillRect(bar);
887 view->PopState();
891 void
892 BPose::DrawToggleSwitch(BRect, BPoseView*)
897 BPoint
898 BPose::Location(const BPoseView* poseView) const
900 float scale = 1.0;
901 if (poseView->ViewMode() == kIconMode)
902 scale = poseView->IconSize() / 32.0;
904 return BPoint(fLocation.x * scale, fLocation.y * scale);
908 void
909 BPose::SetLocation(BPoint point, const BPoseView* poseView)
911 float scale = 1.0;
912 if (poseView->ViewMode() == kIconMode)
913 scale = poseView->IconSize() / 32.0;
915 fLocation = BPoint(floorf(point.x / scale), floorf(point.y / scale));
916 if (isinff(fLocation.x) || isinff(fLocation.y))
917 debugger("BPose::SetLocation() - infinite location");
919 fHasLocation = true;
923 BRect
924 BPose::CalcRect(BPoint loc, const BPoseView* poseView, bool minimalRect) const
926 ASSERT(poseView->ViewMode() == kListMode);
928 BColumn* column = poseView->LastColumn();
929 BRect rect;
930 rect.left = loc.x;
931 rect.top = loc.y;
932 rect.right = loc.x + column->Offset() + column->Width();
933 rect.bottom = rect.top + poseView->ListElemHeight();
935 if (minimalRect) {
936 BTextWidget* widget = WidgetFor(poseView->FirstColumn()->AttrHash());
937 if (widget != NULL) {
938 rect.right = widget->CalcRect(loc, poseView->FirstColumn(),
939 poseView).right;
943 return rect;
947 BRect
948 BPose::CalcRect(const BPoseView* poseView) const
950 ASSERT(poseView->ViewMode() != kListMode);
952 BRect rect;
953 BPoint location = Location(poseView);
954 if (poseView->ViewMode() == kIconMode) {
955 rect.left = location.x;
956 rect.right = rect.left + poseView->IconSizeInt();
958 BTextWidget* widget = WidgetFor(poseView->FirstColumn()->AttrHash());
959 if (widget != NULL) {
960 float textWidth = ceilf(widget->TextWidth(poseView) + 1);
961 if (textWidth > poseView->IconSizeInt()) {
962 rect.left += (poseView->IconSizeInt() - textWidth) / 2;
963 rect.right = rect.left + textWidth;
967 rect.top = location.y;
968 rect.bottom = rect.top + poseView->IconPoseHeight();
969 } else {
970 // MINI_ICON_MODE rect calc
971 rect.left = location.x;
972 rect.top = location.y;
973 rect.right = rect.left + B_MINI_ICON + kMiniIconSeparator;
974 rect.bottom = rect.top + poseView->IconPoseHeight();
975 BTextWidget* widget = WidgetFor(poseView->FirstColumn()->AttrHash());
976 if (widget != NULL)
977 rect.right += ceil(widget->TextWidth(poseView) + 1);
980 return rect;
984 BRect
985 BPose::_IconRect(const BPoseView* poseView, BPoint location) const
987 uint32 size = poseView->IconSizeInt();
988 BRect rect;
989 rect.left = location.x + kListOffset;
990 rect.right = rect.left + size;
991 rect.top = location.y + (poseView->ListElemHeight() - size) / 2.f;
992 rect.bottom = rect.top + size;
993 return rect;
997 #if DEBUG
998 void
999 BPose::PrintToStream()
1001 TargetModel()->PrintToStream();
1002 switch (fClipboardMode) {
1003 case kMoveSelectionTo:
1004 PRINT(("clipboardMode: Cut\n"));
1005 break;
1007 case kCopySelectionTo:
1008 PRINT(("clipboardMode: Copy\n"));
1009 break;
1011 default:
1012 PRINT(("clipboardMode: 0 - not in clipboard\n"));
1013 break;
1015 PRINT(("%sselected\n", IsSelected() ? "" : "not "));
1016 PRINT(("location %s x:%f y:%f\n", HasLocation() ? "" : "unknown ",
1017 HasLocation() ? fLocation.x : 0,
1018 HasLocation() ? fLocation.y : 0));
1019 PRINT(("%s autoplaced \n", WasAutoPlaced() ? "was" : "not"));
1021 #endif