// Select void PropertyListView::Select(PropertyItemView* item) { if (item) { if (modifiers() & B_SHIFT_KEY) { item->SetSelected(!item->IsSelected()); } else if (modifiers() & B_OPTION_KEY) { item->SetSelected(true); int32 firstSelected = _CountItems(); int32 lastSelected = -1; for (int32 i = 0; PropertyItemView* otherItem = _ItemAt(i); i++) { if (otherItem->IsSelected()) { if (i < firstSelected) firstSelected = i; if (i > lastSelected) lastSelected = i; } } if (lastSelected > firstSelected) { for (int32 i = firstSelected; PropertyItemView* otherItem = _ItemAt(i); i++) { if (i > lastSelected) break; otherItem->SetSelected(true); } } } else { for (int32 i = 0; PropertyItemView* otherItem = _ItemAt(i); i++) { otherItem->SetSelected(otherItem == item); } } } _CheckMenuStatus(); }
// _LayoutItems void PropertyListView::_LayoutItems() { // figure out maximum label width float labelWidth = 0.0; for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) { if (item->PreferredLabelWidth() > labelWidth) labelWidth = item->PreferredLabelWidth(); } labelWidth = ceilf(labelWidth); // layout items float top = 0.0; float width = Bounds().Width(); for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) { item->MoveTo(BPoint(0.0, top)); float height = item->PreferredHeight(); item->SetLabelWidth(labelWidth); item->ResizeTo(width, height); item->FrameResized(item->Bounds().Width(), item->Bounds().Height()); top += height + 1.0; AddChild(item); } }
// DeselectAll void PropertyListView::DeselectAll() { for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) { item->SetSelected(false); } _CheckMenuStatus(); }
// _ItemsRect BRect PropertyListView::_ItemsRect() const { float width = Bounds().Width(); float height = -1.0; for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) { height += item->PreferredHeight() + 1.0; } if (height < 0.0) height = 0.0; return BRect(0.0, 0.0, width, height); }
// TabFocus bool PropertyListView::TabFocus(bool shift) { bool result = false; PropertyItemView* item = NULL; if (IsFocus() && !shift) { item = _ItemAt(0); } else { int32 focussedIndex = -1; for (int32 i = 0; PropertyItemView* oldItem = _ItemAt(i); i++) { if (oldItem->IsFocused()) { focussedIndex = shift ? i - 1 : i + 1; break; } } item = _ItemAt(focussedIndex); } if (item) { item->MakeFocus(true); result = true; } return result; }
// _CheckMenuStatus void PropertyListView::_CheckMenuStatus() { if (!fPropertyM || fSuspendUpdates) return; if (!fPropertyObject) { fPropertyM->SetEnabled(false); return; } else fPropertyM->SetEnabled(false); bool gotSelection = false; for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) { if (item->IsSelected()) { gotSelection = true; break; } } fCopyMI->SetEnabled(gotSelection); bool clipboardHasData = false; if (fClipboard->Lock()) { if (BMessage* data = fClipboard->Data()) { clipboardHasData = data->HasMessage("property"); } fClipboard->Unlock(); } fPasteMI->SetEnabled(clipboardHasData); // LanguageManager* m = LanguageManager::Default(); if (IsEditingMultipleObjects()) // fPasteMI->SetLabel(m->GetString(MULTI_PASTE, "Multi paste")); fPasteMI->SetLabel("Multi paste"); else // fPasteMI->SetLabel(m->GetString(PASTE, "Paste")); fPasteMI->SetLabel("Paste"); bool enableMenu = fPropertyObject; if (fPropertyM->IsEnabled() != enableMenu) fPropertyM->SetEnabled(enableMenu); bool gotItems = _CountItems() > 0; fSelectM->SetEnabled(gotItems); }
BLayoutItem* GroupListView::_ItemAt(BLayoutItem* item, BPoint point) { if (RendererLayoutItem* rendererItem = dynamic_cast<RendererLayoutItem*>(item)) return rendererItem; if (BLayout* layout = dynamic_cast<BLayout*>(item)) { for (int i = 0; i < layout->CountItems(); i++) { item = layout->ItemAt(i); if (!item->IsVisible() || !item->Frame().Contains(point)) continue; return _ItemAt(item, point); } } return item; }
void GroupListView::MouseDown(BPoint point) { if (fSelectionMessage == NULL) return; BLayoutItem* item = _ItemAt(GetLayout(), point); if (RendererLayoutItem* rendererItem = dynamic_cast<RendererLayoutItem*>(item)) { BMessage message(*fSelectionMessage); int32 buttons = 0; if (Window()->CurrentMessage() != NULL) buttons = Window()->CurrentMessage()->FindInt32("buttons"); if (buttons != 0) message.AddInt32("buttons", buttons); message.AddInt32("index", rendererItem->Index()); message.AddPointer(rendererItem->Renderer() == fGroupRenderer ? "group" : "item", rendererItem->Item()); fSelectionTarget.SendMessage(&message); } }
// SetTo void PropertyListView::SetTo(PropertyObject* object) { // try to do without rebuilding the list // it should in fact be pretty unlikely that this does not // work, but we keep being defensive if (fPropertyObject && object && fPropertyObject->ContainsSameProperties(*object)) { // iterate over view items and update their value views bool error = false; for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) { Property* property = object->PropertyAt(i); if (!item->AdoptProperty(property)) { // the reason for this can be that the property is // unkown to the PropertyEditorFactory and therefor // there is no editor view at this item fprintf(stderr, "PropertyListView::_SetTo() - " "property mismatch at %ld\n", i); error = true; break; } if (property) item->SetEnabled(property->IsEditable()); } // we didn't need to make empty, but transfer ownership // of the object if (!error) { // if the "adopt" process went only halfway, // some properties of the original object // are still referenced, so we can only // delete the original object if the process // was successful and leak Properties otherwise, // but this case is only theoretical anyways... delete fPropertyObject; } fPropertyObject = object; } else { // remember scroll pos, selection and focused item BPoint scrollOffset = ScrollOffset(); BList selection(20); int32 focused = -1; for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) { if (item->IsSelected()) selection.AddItem((void*)i); if (item->IsFocused()) focused = i; } if (Window()) Window()->BeginViewTransaction(); fSuspendUpdates = true; // rebuild list _MakeEmpty(); fPropertyObject = object; if (fPropertyObject) { // fill with content for (int32 i = 0; Property* property = fPropertyObject->PropertyAt(i); i++) { PropertyItemView* item = new PropertyItemView(property); item->SetEnabled(property->IsEditable()); _AddItem(item); } _LayoutItems(); // restore scroll pos, selection and focus SetScrollOffset(scrollOffset); for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) { if (selection.HasItem((void*)i)) item->SetSelected(true); if (i == focused) item->MakeFocus(true); } } if (Window()) Window()->EndViewTransaction(); fSuspendUpdates = false; SetDataRect(_ItemsRect()); } _UpdateSavedProperties(); _CheckMenuStatus(); Invalidate(); }
// MessageReceived void PropertyListView::MessageReceived(BMessage* message) { switch (message->what) { case MSG_PASTE_PROPERTIES: { if (!fPropertyObject || !fClipboard->Lock()) break; BMessage* data = fClipboard->Data(); if (!data) { fClipboard->Unlock(); break; } PropertyObject propertyObject; BMessage archive; for (int32 i = 0; data->FindMessage("property", i, &archive) >= B_OK; i++) { BArchivable* archivable = instantiate_object(&archive); if (!archivable) continue; // see if this is actually a property Property* property = dynamic_cast<Property*>(archivable); if (property == NULL || !propertyObject.AddProperty(property)) delete archivable; } if (propertyObject.CountProperties() > 0) PasteProperties(&propertyObject); fClipboard->Unlock(); break; } case MSG_COPY_PROPERTIES: { if (!fPropertyObject || !fClipboard->Lock()) break; BMessage* data = fClipboard->Data(); if (!data) { fClipboard->Unlock(); break; } fClipboard->Clear(); for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) { if (!item->IsSelected()) continue; const Property* property = item->GetProperty(); if (property) { BMessage archive; if (property->Archive(&archive) >= B_OK) { data->AddMessage("property", &archive); } } } fClipboard->Commit(); fClipboard->Unlock(); _CheckMenuStatus(); break; } // property selection case MSG_SELECT_ALL: for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) { item->SetSelected(true); } _CheckMenuStatus(); break; case MSG_SELECT_NONE: for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) { item->SetSelected(false); } _CheckMenuStatus(); break; case MSG_INVERT_SELECTION: for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) { item->SetSelected(!item->IsSelected()); } _CheckMenuStatus(); break; default: BView::MessageReceived(message); } }