mirror of https://github.com/aseprite/aseprite.git
Add possibility to overwrite existent layouts
This commit is contained in:
parent
ec41e9fe66
commit
90fae86c9d
|
@ -5,9 +5,7 @@
|
||||||
<vbox>
|
<vbox>
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="@.name" />
|
<label text="@.name" />
|
||||||
<entry id="name" text="@.default_name"
|
<vbox id="name_placeholder" expansive="true" />
|
||||||
maxsize="128" expansive="true"
|
|
||||||
magnet="true" />
|
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<separator horizontal="true" />
|
<separator horizontal="true" />
|
||||||
|
|
|
@ -12,12 +12,14 @@
|
||||||
|
|
||||||
#include "app/app.h"
|
#include "app/app.h"
|
||||||
#include "app/i18n/strings.h"
|
#include "app/i18n/strings.h"
|
||||||
|
#include "app/match_words.h"
|
||||||
#include "app/ui/button_set.h"
|
#include "app/ui/button_set.h"
|
||||||
#include "app/ui/configure_timeline_popup.h"
|
#include "app/ui/configure_timeline_popup.h"
|
||||||
#include "app/ui/main_window.h"
|
#include "app/ui/main_window.h"
|
||||||
#include "app/ui/separator_in_view.h"
|
#include "app/ui/separator_in_view.h"
|
||||||
#include "app/ui/skin/skin_theme.h"
|
#include "app/ui/skin/skin_theme.h"
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
|
#include "ui/entry.h"
|
||||||
#include "ui/listitem.h"
|
#include "ui/listitem.h"
|
||||||
#include "ui/tooltips.h"
|
#include "ui/tooltips.h"
|
||||||
#include "ui/window.h"
|
#include "ui/window.h"
|
||||||
|
@ -79,6 +81,48 @@ private:
|
||||||
obs::scoped_connection m_timelinePosConn;
|
obs::scoped_connection m_timelinePosConn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO this combobox is similar to FileSelector::CustomFileNameEntry
|
||||||
|
// and GotoFrameCommand::TagsEntry
|
||||||
|
class LayoutsEntry : public ComboBox {
|
||||||
|
public:
|
||||||
|
LayoutsEntry(Layouts& layouts) : m_layouts(layouts)
|
||||||
|
{
|
||||||
|
setEditable(true);
|
||||||
|
getEntryWidget()->Change.connect(&LayoutsEntry::onEntryChange, this);
|
||||||
|
fill(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void fill(bool all)
|
||||||
|
{
|
||||||
|
deleteAllItems();
|
||||||
|
|
||||||
|
MatchWords match(getEntryWidget()->text());
|
||||||
|
|
||||||
|
bool matchAny = false;
|
||||||
|
for (auto& layout : m_layouts) {
|
||||||
|
if (match(layout->name())) {
|
||||||
|
matchAny = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto& layout : m_layouts) {
|
||||||
|
if (all || !matchAny || match(layout->name()))
|
||||||
|
addItem(layout->name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onEntryChange()
|
||||||
|
{
|
||||||
|
closeListBox();
|
||||||
|
fill(false);
|
||||||
|
if (getItemCount() > 0)
|
||||||
|
openListBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
Layouts& m_layouts;
|
||||||
|
};
|
||||||
|
|
||||||
}; // namespace
|
}; // namespace
|
||||||
|
|
||||||
class LayoutSelector::LayoutItem : public ListItem {
|
class LayoutSelector::LayoutItem : public ListItem {
|
||||||
|
@ -95,13 +139,17 @@ public:
|
||||||
const std::string& text,
|
const std::string& text,
|
||||||
const LayoutPtr layout = nullptr)
|
const LayoutPtr layout = nullptr)
|
||||||
: ListItem(text)
|
: ListItem(text)
|
||||||
, m_selector(selector)
|
|
||||||
, m_id(id)
|
, m_id(id)
|
||||||
|
, m_selector(selector)
|
||||||
, m_layout(layout)
|
, m_layout(layout)
|
||||||
{
|
{
|
||||||
ASSERT((id != USER_DEFINED && layout == nullptr) || (id == USER_DEFINED && layout != nullptr));
|
ASSERT((id != USER_DEFINED && layout == nullptr) || (id == USER_DEFINED && layout != nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Layout* layout() const { return m_layout.get(); }
|
||||||
|
|
||||||
|
void setLayout(const LayoutPtr& layout) { m_layout = layout; }
|
||||||
|
|
||||||
void selectImmediately()
|
void selectImmediately()
|
||||||
{
|
{
|
||||||
MainWindow* win = App::instance()->mainWindow();
|
MainWindow* win = App::instance()->mainWindow();
|
||||||
|
@ -126,13 +174,23 @@ public:
|
||||||
|
|
||||||
switch (m_id) {
|
switch (m_id) {
|
||||||
case LayoutId::SAVE_LAYOUT: {
|
case LayoutId::SAVE_LAYOUT: {
|
||||||
gen::NewLayout window;
|
// Select the "Layout" separator (it's like selecting nothing)
|
||||||
window.name()->setText(
|
// TODO improve the ComboBox to select a real "nothing" (with
|
||||||
fmt::format("{} ({})", window.name()->text(), m_selector->m_layouts.size() + 1));
|
// a placeholder text)
|
||||||
|
m_selector->m_comboBox.setSelectedItemIndex(0);
|
||||||
|
|
||||||
|
gen::NewLayout window;
|
||||||
|
LayoutsEntry name(m_selector->m_layouts);
|
||||||
|
name.getEntryWidget()->setMaxTextLength(128);
|
||||||
|
name.setFocusMagnet(true);
|
||||||
|
name.setValue(fmt::format("{} ({})",
|
||||||
|
Strings::new_layout_default_name(),
|
||||||
|
m_selector->m_layouts.size() + 1));
|
||||||
|
|
||||||
|
window.namePlaceholder()->addChild(&name);
|
||||||
window.openWindowInForeground();
|
window.openWindowInForeground();
|
||||||
if (window.closer() == window.ok()) {
|
if (window.closer() == window.ok()) {
|
||||||
auto layout = Layout::MakeFromDock(window.name()->text(), win->customizableDock());
|
auto layout = Layout::MakeFromDock(name.getValue(), win->customizableDock());
|
||||||
|
|
||||||
m_selector->addLayout(layout);
|
m_selector->addLayout(layout);
|
||||||
}
|
}
|
||||||
|
@ -195,12 +253,23 @@ LayoutSelector::~LayoutSelector()
|
||||||
|
|
||||||
void LayoutSelector::addLayout(const LayoutPtr& layout)
|
void LayoutSelector::addLayout(const LayoutPtr& layout)
|
||||||
{
|
{
|
||||||
|
bool added = m_layouts.addLayout(layout);
|
||||||
|
if (added) {
|
||||||
auto item = m_comboBox.addItem(
|
auto item = m_comboBox.addItem(
|
||||||
new LayoutItem(this, LayoutItem::USER_DEFINED, layout->name(), layout));
|
new LayoutItem(this, LayoutItem::USER_DEFINED, layout->name(), layout));
|
||||||
|
|
||||||
m_layouts.addLayout(layout);
|
|
||||||
|
|
||||||
m_comboBox.setSelectedItemIndex(item);
|
m_comboBox.setSelectedItemIndex(item);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (auto item : m_comboBox) {
|
||||||
|
if (auto layoutItem = dynamic_cast<LayoutItem*>(item)) {
|
||||||
|
if (layoutItem->layout() && layoutItem->layout()->name() == layout->name()) {
|
||||||
|
layoutItem->setLayout(layout);
|
||||||
|
m_comboBox.setSelectedItem(item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutSelector::onAnimationFrame()
|
void LayoutSelector::onAnimationFrame()
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "app/xml_exception.h"
|
#include "app/xml_exception.h"
|
||||||
#include "base/fs.h"
|
#include "base/fs.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
|
@ -37,9 +38,19 @@ Layouts::~Layouts()
|
||||||
save(m_userLayoutsFilename);
|
save(m_userLayoutsFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layouts::addLayout(const LayoutPtr& layout)
|
bool Layouts::addLayout(const LayoutPtr& layout)
|
||||||
{
|
{
|
||||||
|
auto it = std::find_if(m_layouts.begin(), m_layouts.end(), [layout](const LayoutPtr& l) {
|
||||||
|
return l->name() == layout->name();
|
||||||
|
});
|
||||||
|
if (it != m_layouts.end()) {
|
||||||
|
*it = layout; // Replace existent layout
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
m_layouts.push_back(layout);
|
m_layouts.push_back(layout);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layouts::load(const std::string& fn)
|
void Layouts::load(const std::string& fn)
|
||||||
|
|
|
@ -22,7 +22,9 @@ public:
|
||||||
|
|
||||||
size_t size() const { return m_layouts.size(); }
|
size_t size() const { return m_layouts.size(); }
|
||||||
|
|
||||||
void addLayout(const LayoutPtr& layout);
|
// Returns true if the layout is added, or false if it was
|
||||||
|
// replaced.
|
||||||
|
bool addLayout(const LayoutPtr& layout);
|
||||||
|
|
||||||
// To iterate layouts
|
// To iterate layouts
|
||||||
using List = std::vector<LayoutPtr>;
|
using List = std::vector<LayoutPtr>;
|
||||||
|
|
Loading…
Reference in New Issue