Skip to content

Commit

Permalink
UI|Home: Usability improvements for the Packages dialog
Browse files Browse the repository at this point in the history
Selecting packages for a game is now more streamlined. Packages can
be added and removed with a single mouse click. Clicking on a
selected package will highlight it on the right-side package browser.
  • Loading branch information
skyjake committed Apr 23, 2016
1 parent 965e513 commit 739be6e
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 174 deletions.
1 change: 1 addition & 0 deletions doomsday/apps/client/include/ui/widgets/homeitemwidget.h
Expand Up @@ -43,6 +43,7 @@ class HomeItemWidget : public de::GuiWidget, public de::IAssetGroup
de::LabelWidget &label();

void addButton(de::ButtonWidget *button);
void setKeepButtonsVisible(bool yes);

virtual void setSelected(bool selected);
bool isSelected() const;
Expand Down
4 changes: 4 additions & 0 deletions doomsday/apps/client/include/ui/widgets/homemenuwidget.h
Expand Up @@ -49,6 +49,10 @@ class HomeMenuWidget : public de::MenuWidget
*/
void setSelectedIndex(int index);

signals:
void selectedIndexChanged(int index);
void itemClicked(int index);

protected slots:
void mouseActivityInItem();
void itemSelectionChanged();
Expand Down
13 changes: 13 additions & 0 deletions doomsday/apps/client/include/ui/widgets/packageswidget.h
Expand Up @@ -55,11 +55,24 @@ class PackagesWidget : public de::GuiWidget, public de::IPersistent
void setButtonHandler(IButtonHandler &buttonHandler);
void setButtonLabels(de::String const &buttonLabel,
de::String const &highlightedButtonLabel);
void setButtonImages(de::DotPath const &styleId,
de::DotPath const &highlightedStyleId);
void setActionButtonAlwaysShown(bool showActions);

void setColorTheme(ColorTheme unselectedItem, ColorTheme selectedItem,
ColorTheme loadedUnselectedItem, ColorTheme loadedSelectedItem);

void populate();
void updateItems();

/**
* Finds the item for a package, if it is currently listed.
* @param packageId Package identifier.
* @return Item.
*/
de::ui::Item const *itemForPackage(de::String const &packageId) const;

void scrollToPackage(de::String const &packageId) const;

de::LineEditWidget &searchTermsEditor();

Expand Down
202 changes: 56 additions & 146 deletions doomsday/apps/client/src/ui/dialogs/packagesdialog.cpp
Expand Up @@ -45,6 +45,7 @@ DENG_GUI_PIMPL(PackagesDialog)
, public ChildWidgetOrganizer::IWidgetFactory
, public PackagesWidget::IPackageStatus
, public PackagesWidget::IButtonHandler
, DENG2_OBSERVES(Widget, ChildAddition)
{
StringList requiredPackages; // loaded first, cannot be changed
StringList selectedPackages;
Expand Down Expand Up @@ -89,13 +90,6 @@ DENG_GUI_PIMPL(PackagesDialog)
return _file;
}

/*void setFile(File const &packFile)
{
file = &packFile;
info = &file->objectNamespace().subrecord(Package::VAR_PACKAGE);
notifyChange();
}*/

private:
File const *_file = nullptr;
Record const *_info = nullptr;
Expand All @@ -108,26 +102,24 @@ DENG_GUI_PIMPL(PackagesDialog)
class SelectedPackageWidget : public HomeItemWidget
{
public:
SelectedPackageWidget(SelectedPackageItem const &item)
: _item(&item)
SelectedPackageWidget(SelectedPackageItem const &item,
PackagesDialog &owner)
: _owner(owner)
, _item(&item)
{
useColorTheme(Normal, Inverted);
useColorTheme(Normal, Normal);

_infoButton = new PopupButtonWidget;
_infoButton->setText(tr("..."));
_infoButton->setFont("small");
_infoButton->margins().setTopBottom("unit");
_infoButton->setPopup([this] (PopupButtonWidget const &)
_removeButton = new ButtonWidget;
_removeButton->setImage(new StyleProceduralImage("close.ringless", *_removeButton));
_removeButton->setOverrideImageSize(style().fonts().font("small").height().value());
_removeButton->margins().setTopBottom("unit");
_removeButton->setActionFn([this] ()
{
auto *pop = new PopupMenuWidget;
pop->setColorTheme(Inverted);
pop->items() << new ui::SubwidgetItem(
tr("Info"), ui::Down,
[this] () -> PopupWidget * { return makeInfoPopup(); });
return pop;
}
, ui::Down);
addButton(_infoButton);
_owner.d->removePackage(packageId());
_owner.d->browser->updateItems();
});
addButton(_removeButton);
setKeepButtonsVisible(true);

// Package icon.
icon().set(Background());
Expand All @@ -137,90 +129,8 @@ DENG_GUI_PIMPL(PackagesDialog)
Rule const &height = style().fonts().font("default").height();
icon().setOverrideImageSize(height.value());
icon().rule().setInput(Rule::Width, height + rule("dialog.gap")*2);

/*
add(_title = new LabelWidget);
_title->setSizePolicy(ui::Fixed, ui::Expand);
_title->setAlignment(ui::AlignLeft);
_title->setTextLineAlignment(ui::AlignLeft);
_title->margins().setBottom("").setLeft("unit");
add(_subtitle = new LabelWidget);
_subtitle->setSizePolicy(ui::Fixed, ui::Expand);
_subtitle->setAlignment(ui::AlignLeft);
_subtitle->setTextLineAlignment(ui::AlignLeft);
_subtitle->setFont("small");
_subtitle->setTextColor("accent");
_subtitle->margins().setTop("").setBottom("unit").setLeft("unit");
add(_loadButton = new ButtonWidget);
_loadButton->setSizePolicy(ui::Expand, ui::Expand);
_loadButton->setAction(new LoadAction(*this));
add(_infoButton = new PopupButtonWidget);
_infoButton->setSizePolicy(ui::Expand, ui::Fixed);
_infoButton->setText(_E(s)_E(B) + tr("..."));
_infoButton->setPopup([this] (PopupButtonWidget const &) {
return makeInfoPopup();
}, ui::Left);
createTagButtons();
AutoRef<Rule> titleWidth(rule().width() -
_loadButton->rule().width() -
_infoButton->rule().width());
_title->rule()
.setInput(Rule::Width, titleWidth)
.setInput(Rule::Left, rule().left())
.setInput(Rule::Top, rule().top());
_subtitle->rule()
.setInput(Rule::Width, titleWidth)
.setInput(Rule::Left, rule().left())
.setInput(Rule::Top, _title->rule().bottom());
_loadButton->rule()
.setInput(Rule::Right, rule().right() - _infoButton->rule().width())
.setMidAnchorY(rule().midY());
_infoButton->rule()
.setInput(Rule::Right, rule().right())
.setInput(Rule::Height, _loadButton->rule().height())
.setMidAnchorY(rule().midY());
rule().setInput(Rule::Width, rule("dialog.packages.width"))
.setInput(Rule::Height, _title->rule().height() +
_subtitle->rule().height() + _tags.at(0)->rule().height());
*/
}
/*
void createTagButtons()
{
SequentialLayout layout(_subtitle->rule().left(),
_subtitle->rule().bottom(), ui::Right);
for(QString tag : Package::tags(*_item->file))
{
auto *btn = new ButtonWidget;
btn->setText(_E(l) + tag.toLower());
updateTagButtonStyle(btn, "accent");
btn->setSizePolicy(ui::Expand, ui::Expand);
btn->margins()
.setTop("unit").setBottom("unit")
.setLeft("gap").setRight("gap");
add(btn);
layout << *btn;
_tags.append(btn);
}
}

void updateTagButtonStyle(ButtonWidget *tag, String const &color)
{
tag->setFont("small");
tag->setTextColor(color);
tag->set(Background(Background::Rounded, style().colors().colorf(color), 6));
}*/

void updateContents()
{
if(_item->info())
Expand All @@ -231,33 +141,6 @@ DENG_GUI_PIMPL(PackagesDialog)
{
label().setText(_item->packageId());
}

/*
_subtitle->setText(packageId());
String auxColor = "accent";
if(isLoaded())
{
_loadButton->setText(tr("Unload"));
_loadButton->setTextColor("altaccent");
_loadButton->setBorderColor("altaccent");
_title->setFont("choice.selected");
auxColor = "altaccent";
}
else
{
_loadButton->setText(tr("Load"));
_loadButton->setTextColor("text");
_loadButton->setBorderColor("text");
_title->setFont("default");
}
_subtitle->setTextColor(auxColor);
for(ButtonWidget *b : _tags)
{
updateTagButtonStyle(b, auxColor);
}*/
}

String packageId() const
Expand All @@ -271,13 +154,9 @@ DENG_GUI_PIMPL(PackagesDialog)
}

private:
PackagesDialog &_owner;
SelectedPackageItem const *_item;
//LabelWidget *_title;
//LabelWidget *_subtitle;
//QList<ButtonWidget *> _tags;
PopupButtonWidget *_infoButton;
//ButtonWidget *_loadButton;
//PopupButtonWidget *_infoButton;
ButtonWidget *_removeButton;
};

Instance(Public *i) : Base(i)
Expand Down Expand Up @@ -318,13 +197,27 @@ DENG_GUI_PIMPL(PackagesDialog)
.setInput(Rule::Top, gameTitle->rule().bottom())
.setInput(Rule::Width, rule("dialog.packages.width"));
menu->organizer().setWidgetFactory(*this);
menu->audienceForChildAddition() += this;
self.leftArea().enableIndicatorDraw(true);

QObject::connect(menu, &HomeMenuWidget::itemClicked, [this] (int index)
{
// Update the remove button position.
if(index >= 0)
{
browser->scrollToPackage(menu->items().at(index)
.as<SelectedPackageItem>().packageId());
}
});

// Package browser.
self.rightArea().add(browser = new PackagesWidget);
browser->setActionButtonAlwaysShown(true);
browser->setPackageStatus(*this);
browser->setButtonHandler(*this);
browser->setButtonLabels(tr("Add"), tr("Remove"));
//browser->setButtonLabels(tr("Add"), tr("Remove"));
browser->setButtonLabels("", "");
browser->setButtonImages("create", "close.ringless");
//browser->setColorTheme(Normal, Normal, Normal, Normal);
browser->rule()
.setInput(Rule::Left, self.rightArea().contentRule().left())
Expand All @@ -333,6 +226,11 @@ DENG_GUI_PIMPL(PackagesDialog)
self.rightArea().enableIndicatorDraw(true);
}

~Instance()
{
menu->audienceForChildAddition() -= this;
}

void populate()
{
menu->items().clear();
Expand Down Expand Up @@ -380,7 +278,7 @@ DENG_GUI_PIMPL(PackagesDialog)

GuiWidget *makeItemWidget(ui::Item const &item, GuiWidget const *)
{
return new SelectedPackageWidget(item.as<SelectedPackageItem>());
return new SelectedPackageWidget(item.as<SelectedPackageItem>(), self);
}

void updateItemWidget(GuiWidget &widget, ui::Item const &)
Expand All @@ -402,14 +300,25 @@ DENG_GUI_PIMPL(PackagesDialog)
}
else
{
selectedPackages.removeOne(packageId);
auto pos = menu->items().findData(packageId);
DENG2_ASSERT(pos != ui::Data::InvalidPos);
menu->items().remove(pos);
removePackage(packageId);
}

updateNothingIndicator();
}

void removePackage(String const &packageId)
{
selectedPackages.removeOne(packageId);
auto pos = menu->items().findData(packageId);
DENG2_ASSERT(pos != ui::Data::InvalidPos);
menu->items().remove(pos);
}

void widgetChildAdded(Widget &child)
{
menu->setSelectedIndex(menu->items().find(
*menu->organizer().findItemForWidget(child.as<GuiWidget>())));
}
};

PackagesDialog::PackagesDialog(String const &titleText)
Expand All @@ -426,7 +335,8 @@ PackagesDialog::PackagesDialog(String const &titleText)
}
heading().setImage(style().images().image("package"));
buttons()
<< new DialogButtonItem(Default | Accept, tr("Close"))
<< new DialogButtonItem(Default | Accept, tr("OK"))
<< new DialogButtonItem(Reject, tr("Cancel"))
<< new DialogButtonItem(Action, style().images().image("refresh"),
new SignalAction(this, SLOT(refreshPackages())));

Expand Down
16 changes: 15 additions & 1 deletion doomsday/apps/client/src/ui/widgets/homeitemwidget.cpp
Expand Up @@ -96,6 +96,7 @@ DENG_GUI_PIMPL(HomeItemWidget)
AnimationRule *labelRightMargin;
Rule const *buttonsWidth = nullptr;
bool selected = false;
bool keepButtonsVisible = false;
DotPath bgColor { "transparent" };
DotPath selectedBgColor { "background" };
DotPath textColor { "text" };
Expand Down Expand Up @@ -242,7 +243,7 @@ void HomeItemWidget::setSelected(bool selected)
{
d->showButtons(true);
}
else
else if(!d->keepButtonsVisible)
{
d->showButtons(false);
}
Expand Down Expand Up @@ -370,3 +371,16 @@ void HomeItemWidget::addButton(ButtonWidget *button)
button->hide();
d->updateButtonLayout();
}

void HomeItemWidget::setKeepButtonsVisible(bool yes)
{
d->keepButtonsVisible = yes;
if(yes)
{
d->showButtons(true);
}
else if(!d->selected)
{
d->showButtons(false);
}
}

0 comments on commit 739be6e

Please sign in to comment.