Initial work on #106.

Moved the load order preview window to a new header/source file, and cut
out the move up/down buttons. Started to implement mini editor.
This commit is contained in:
WrinklyNinja
2014-02-09 09:55:26 +00:00
parent 81b61ea38d
commit 1771c0830f
6 changed files with 239 additions and 219 deletions
+1
View File
@@ -25,6 +25,7 @@ set (BOSS_GUI_SRC ${BOSS_SRC}
"${CMAKE_SOURCE_DIR}/src/gui/settings.cpp"
"${CMAKE_SOURCE_DIR}/src/gui/editor.cpp"
"${CMAKE_SOURCE_DIR}/src/gui/viewer.cpp"
"${CMAKE_SOURCE_DIR}/src/gui/sorting.cpp"
"${CMAKE_SOURCE_DIR}/src/resource.rc")
set (BOSS_API_SRC ${BOSS_SRC}
-3
View File
@@ -61,13 +61,10 @@ public:
void OnPluginCopyName(wxCommandEvent& event);
void OnPluginCopyMetadata(wxCommandEvent& event);
void OnPluginClearMetadata(wxCommandEvent& event);
void OnEnabledToggle(wxCommandEvent& event);
void OnPriorityChange(wxSpinEvent& event);
void OnListBookChange(wxBookCtrlEvent& event);
void OnAddRow(wxCommandEvent& event);
void OnEditRow(wxCommandEvent& event);
void OnRemoveRow(wxCommandEvent& event);
void OnRecalc(wxCommandEvent& event);
void OnRowSelect(wxListEvent& event);
void OnQuit(wxCommandEvent& event);
private:
+4 -197
View File
@@ -24,6 +24,7 @@
#include "settings.h"
#include "editor.h"
#include "viewer.h"
#include "sorting.h"
#include "../backend/globals.h"
#include "../backend/metadata.h"
@@ -680,7 +681,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) {
if (preview.ShowModal() == wxID_OK) {
BOOST_LOG_TRIVIAL(debug) << "Load order accepted.";
list<boss::Plugin> newPluginsList, editedPlugins;
newPluginsList = preview.GetLoadOrder();
/*newPluginsList = preview.GetLoadOrder();
BOOST_LOG_TRIVIAL(trace) << "Building list of edited plugins.";
for (list<boss::Plugin>::iterator it=newPluginsList.begin(),endit=newPluginsList.end(); it != endit; ++it) {
@@ -746,7 +747,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) {
uout << yout.c_str();
uout.close();
}
*/
//Now set load order.
BOOST_LOG_TRIVIAL(debug) << "Setting load order.";
try {
@@ -1093,198 +1094,4 @@ void Launcher::OnAbout(wxCommandEvent& event) {
"along with this program. If not, see <http://www.gnu.org/licenses/>.");
aboutInfo.SetIcon(wxIconLocation("BOSS.exe"));
wxAboutBox(aboutInfo);
}
LoadOrderPreview::LoadOrderPreview(wxWindow *parent, const wxString title, const std::list<boss::Plugin>& plugins, const boss::Game& game) : wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), _plugins(plugins), _game(game) {
//Init controls.
_loadOrder = new wxListView(this, LIST_LoadOrder, wxDefaultPosition, wxDefaultSize, wxLC_REPORT);
_moveUp = new wxButton(this, BUTTON_MoveUp, translate("Up"));
_moveDown = new wxButton(this, BUTTON_MoveDown, translate("Down"));
//Populate list.
_loadOrder->AppendColumn(translate("Load Order"));
size_t i=0;
for (list<boss::Plugin>::const_iterator it=plugins.begin(), endit=plugins.end(); it != endit; ++it, ++i) {
_loadOrder->InsertItem(i, FromUTF8(it->Name()));
if (it->FormIDs().empty()) {
_loadOrder->SetItemTextColour(i, wxColour(122, 122, 122));
}
else if (it->LoadsBSA(_game)) {
_loadOrder->SetItemTextColour(i, wxColour(0, 142, 219));
}
}
_loadOrder->SetColumnWidth(0, wxLIST_AUTOSIZE);
//Set up event handling.
Bind(wxEVT_BUTTON, &LoadOrderPreview::OnMoveUp, this, BUTTON_MoveUp);
Bind(wxEVT_BUTTON, &LoadOrderPreview::OnMoveDown, this, BUTTON_MoveDown);
Bind(wxEVT_LIST_ITEM_SELECTED, &LoadOrderPreview::OnPluginSelect, this, LIST_LoadOrder);
//Set up layout.
wxBoxSizer * bigBox = new wxBoxSizer(wxVERTICAL);
bigBox->Add(_loadOrder, 1, wxEXPAND|wxALL, 15);
wxBoxSizer * hbox = new wxBoxSizer(wxHORIZONTAL);
hbox->Add(_moveUp, 0, wxRIGHT, 5);
hbox->Add(_moveDown, 0, wxLEFT, 5);
bigBox->Add(hbox, 0, wxALIGN_RIGHT|wxBOTTOM|wxRIGHT, 15);
bigBox->Add(new wxStaticText(this, wxID_ANY, translate("Please submit any alterations made for reasons other than user preference \nto the BOSS team so that they may include the changes in the masterlist.")), 0, wxEXPAND|wxLEFT|wxRIGHT|wxBOTTOM, 15);
//Need to add 'OK' and 'Cancel' buttons.
wxSizer * sizer = CreateSeparatedButtonSizer(wxOK|wxCANCEL);
//Now add TabHolder and OK button to window sizer.
if (sizer != NULL)
bigBox->Add(sizer, 0, wxEXPAND|wxLEFT|wxBOTTOM|wxRIGHT, 15);
//Set initial up/down button states.
_moveUp->Enable(false);
_moveDown->Enable(false);
//Now set the layout and sizes.
SetBackgroundColour(wxColour(255,255,255));
SetIcon(wxIconLocation("BOSS.exe"));
SetSizerAndFit(bigBox);
}
void LoadOrderPreview::OnPluginSelect(wxListEvent& event) {
_moveUp->Enable(true);
_moveDown->Enable(true);
}
void LoadOrderPreview::OnMoveUp(wxCommandEvent& event) {
BOOST_LOG_TRIVIAL(debug) << "Moving plugin(s) up the load order.";
long selected = _loadOrder->GetFirstSelected();
if (selected == 0)
return;
while (selected != -1) {
wxString selectedText = _loadOrder->GetItemText(selected);
wxString aboveText = _loadOrder->GetItemText(selected - 1);
BOOST_LOG_TRIVIAL(trace) << "Moving plugin \"" << string(selectedText.ToUTF8());
//Check that move is OK.
list<boss::Plugin>::const_iterator selectedPlugin = find(_plugins.begin(), _plugins.end(), boss::Plugin(string(selectedText.ToUTF8())));
list<boss::Plugin>::const_iterator abovePlugin = find(_plugins.begin(), _plugins.end(), boss::Plugin(string(aboveText.ToUTF8())));
if (selectedPlugin != _plugins.end() && abovePlugin != _plugins.end()) {
if (selectedPlugin->MustLoadAfter(*abovePlugin)) {
BOOST_LOG_TRIVIAL(error) << "Cannot load \"" << selectedPlugin->Name() << "\" before \"" << abovePlugin->Name() << "\".";
wxMessageBox(
FromUTF8(format(loc::translate("Error: Cannot load \"%1%\" before \"%2%\".")) % selectedPlugin->Name() % abovePlugin->Name()),
translate("BOSS: Error"),
wxOK | wxICON_ERROR,
NULL);
selected = _loadOrder->GetNextSelected(selected);
continue;
}
}
_loadOrder->SetItemText(selected, aboveText);
_loadOrder->SetItemText(selected - 1, selectedText);
_movedPlugins.insert(string(selectedText.ToUTF8()));
_loadOrder->Select(selected, false);
_loadOrder->Select(selected - 1, true);
selected = _loadOrder->GetNextSelected(selected);
}
BOOST_LOG_TRIVIAL(debug) << "Plugin(s) moved up.";
}
void LoadOrderPreview::OnMoveDown(wxCommandEvent& event) {
BOOST_LOG_TRIVIAL(debug) << "Moving plugin(s) down the load order.";
long i=_loadOrder->GetItemCount() - 1;
if (_loadOrder->IsSelected(i))
return;
--i;
for (i; i > -1; --i) {
if (_loadOrder->IsSelected(i)) {
wxString selectedText = _loadOrder->GetItemText(i);
wxString belowText = _loadOrder->GetItemText(i + 1);
BOOST_LOG_TRIVIAL(trace) << "Moving plugin \"" << string(selectedText.ToUTF8());
//Check that move is OK.
list<boss::Plugin>::const_iterator selectedPlugin = find(_plugins.begin(), _plugins.end(), boss::Plugin(string(selectedText.ToUTF8())));
list<boss::Plugin>::const_iterator belowPlugin = find(_plugins.begin(), _plugins.end(), boss::Plugin(string(belowText.ToUTF8())));
if (selectedPlugin != _plugins.end() && belowPlugin != _plugins.end()) {
if (belowPlugin->MustLoadAfter(*selectedPlugin)) {
BOOST_LOG_TRIVIAL(error) << "Cannot load \"" << belowPlugin->Name() << "\" before \"" << selectedPlugin->Name() << "\".";
wxMessageBox(
FromUTF8(format(loc::translate("Error: Cannot load \"%1%\" before \"%2%\".")) % belowPlugin->Name() % selectedPlugin->Name()),
translate("BOSS: Error"),
wxOK | wxICON_ERROR,
NULL);
continue;
}
}
_loadOrder->SetItemText(i, belowText);
_loadOrder->SetItemText(i + 1, selectedText);
_movedPlugins.insert(string(selectedText.ToUTF8()));
_loadOrder->Select(i, false);
_loadOrder->Select(i + 1, true);
}
}
BOOST_LOG_TRIVIAL(debug) << "Plugin(s) moved down.";
}
std::list<boss::Plugin> LoadOrderPreview::GetLoadOrder() const {
BOOST_LOG_TRIVIAL(debug) << "Getting full load order from preview window.";
list<boss::Plugin> plugins;
bool wasMovedUp = false;
for (size_t i=0,max=_loadOrder->GetItemCount(); i < max; ++i) {
string name = string(_loadOrder->GetItemText(i).ToUTF8());
list<boss::Plugin>::const_iterator it = find(_plugins.begin(), _plugins.end(), boss::Plugin(name));
if (it == _plugins.end())
continue;
plugins.push_back(*it);
if (wasMovedUp) {
BOOST_LOG_TRIVIAL(trace) << "The previous plugin was moved up in the load order, so adding it to the 'load after' set for the current plugin.";
list<boss::Plugin>::const_iterator jt = ----plugins.end();
set<boss::File> loadAfter = plugins.back().LoadAfter();
loadAfter.insert(File(jt->Name()));
plugins.back().LoadAfter(loadAfter);
wasMovedUp = false;
}
if (_movedPlugins.find(name) != _movedPlugins.end()) {
BOOST_LOG_TRIVIAL(trace) << "The current plugin was moved - checking if it was moved up or down.";
//Check if this plugin has been moved earlier or later by comparing distances in the original list and the new one.
size_t newDist = plugins.size() - 1;
size_t oldDist = distance(_plugins.begin(), it);
if (newDist > oldDist) {
BOOST_LOG_TRIVIAL(trace) << "The current plugin was moved down, add the preceding plugin to the current plugin's 'load after' set.";
//Record the preceding plugin in this plugin's "load after" set.
list<boss::Plugin>::const_iterator jt = ----plugins.end();
set<boss::File> loadAfter = plugins.back().LoadAfter();
loadAfter.insert(File(jt->Name()));
plugins.back().LoadAfter(loadAfter);
} else {
BOOST_LOG_TRIVIAL(trace) << "The current plugin was moved up.";
//Record this plugin in the following plugin's "load after" set.
wasMovedUp = true;
}
}
}
return plugins;
}
}
-19
View File
@@ -70,23 +70,4 @@ private:
std::vector<boss::Game>& _games;
};
class LoadOrderPreview : public wxDialog {
public:
LoadOrderPreview(wxWindow *parent, const wxString title, const std::list<boss::Plugin>& plugins, const boss::Game& game);
void OnPluginSelect(wxListEvent& event);
void OnMoveUp(wxCommandEvent& event);
void OnMoveDown(wxCommandEvent& event);
std::list<boss::Plugin> GetLoadOrder() const;
private:
wxListView * _loadOrder;
wxButton * _moveUp;
wxButton * _moveDown;
const std::list<boss::Plugin> _plugins;
std::set<std::string> _movedPlugins;
const boss::Game& _game;
};
#endif
+168
View File
@@ -0,0 +1,168 @@
/* BOSS
A plugin load order optimiser for games that use the esp/esm plugin system.
Copyright (C) 2013-2014 WrinklyNinja
This file is part of BOSS.
BOSS is free software: you can redistribute
it and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
BOSS is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with BOSS. If not, see
<http://www.gnu.org/licenses/>.
*/
#include "sorting.h"
#include "../backend/helpers.h"
using namespace std;
MiniEditor::MiniEditor(wxWindow *parent, const wxString& title, const std::vector<boss::Plugin>& plugins, const boss::Game& game) : wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), _basePlugins(plugins) {
//Initialise controls.
pluginText = new wxStaticText(this, wxID_ANY, "");
prioritySpin = new wxSpinCtrl(this, wxID_ANY, "0");
prioritySpin->SetRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
filterCheckbox = new wxCheckBox(this, wxID_ANY, translate("Show only conflicting plugins."));
pluginList = new wxListView(this, LIST_Plugins, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL);
loadAfterList = new wxListView(this, LIST_LoadAfter, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL);
removeBtn = new wxButton(this, BUTTON_RemoveRow, translate("Remove"));
applyBtn = new wxButton(this, BUTTON_Apply, translate("Apply Changes"));
cancelBtn = new wxButton(this, BUTTON_Cancel, translate("Cancel"));
wxMenu * pluginMenu = new wxMenu();
//Set up list columns.
pluginList->AppendColumn(translate("Plugin"));
pluginList->AppendColumn(translate("Priority"));
loadAfterList->AppendColumn(translate("Filename"));
//Set up plugin right-click menu.
pluginMenu->Append(MENU_CopyName, translate("Copy Name"));
pluginMenu->Append(MENU_CopyMetadata, translate("Copy Metadata As Text"));
pluginMenu->Append(MENU_ClearMetadata, translate("Remove All User-Added Metadata"));
//Initialise control states.
removeBtn->Enable(false);
prioritySpin->Enable(false);
filterCheckbox->Enable(false);
//Make plugin name bold text.
pluginText->SetFont(pluginText->GetFont().Bold());
//Set up layout.
wxBoxSizer * bigBox = new wxBoxSizer(wxHORIZONTAL);
bigBox->Add(pluginList, 1, wxEXPAND | wxALL, 10);
wxBoxSizer * mainBox = new wxBoxSizer(wxVERTICAL);
mainBox->Add(pluginText, 0, wxTOP | wxBOTTOM, 10);
wxBoxSizer * hbox1 = new wxBoxSizer(wxHORIZONTAL);
hbox1->Add(new wxStaticText(this, wxID_ANY, translate("Priority: ")), 0, wxALIGN_RIGHT | wxLEFT | wxRIGHT, 5);
hbox1->Add(prioritySpin, 0, wxALIGN_RIGHT);
mainBox->Add(hbox1, 0, wxEXPAND | wxALIGN_RIGHT | wxTOP | wxBOTTOM, 5);
mainBox->Add(loadAfterList, 1, wxEXPAND);
mainBox->Add(removeBtn, 0, wxALIGN_RIGHT, 5);
bigBox->Add(mainBox, 2, wxEXPAND | wxTOP | wxBOTTOM | wxRIGHT, 10);
//Need to add 'Yes' and 'No' buttons.
wxSizer * sizer = CreateSeparatedButtonSizer(wxYES | wxNO | wxCANCEL);
//Now add buttons to window sizer.
if (sizer != NULL)
bigBox->Add(sizer, 0, wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT, 15);
//Fill pluginList with the contents of basePlugins.
for (int i = 0, max = _basePlugins.size(); i < max; ++i) {
pluginList->InsertItem(i, FromUTF8(_basePlugins[i].Name()));
pluginList->SetItem(i, 2, FromUTF8(boss::IntToString(_basePlugins[i].Priority())));
if (_basePlugins[i].LoadsBSA(game)) {
pluginList->SetItemTextColour(i, wxColour(0, 142, 219));
}
if (std::find(_editedPlugins.begin(), _editedPlugins.end(), _basePlugins[i]) != _editedPlugins.end()) {
pluginList->SetItemFont(i, wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold());
}
}
pluginList->SetColumnWidth(0, wxLIST_AUTOSIZE);
SetBackgroundColour(wxColour(255, 255, 255));
SetIcon(wxIconLocation("BOSS.exe"));
SetSizerAndFit(bigBox);
Layout();
}
void MiniEditor::OnPluginSelect(wxListEvent& event) {
}
void MiniEditor::OnPluginListRightClick(wxListEvent& event) {
}
void MiniEditor::OnPluginCopy(wxCommandEvent& event) {
}
void MiniEditor::OnFilterToggle(wxCommandEvent& event) {
}
void MiniEditor::OnQuit(wxCommandEvent& event) {
}
LoadOrderPreview::LoadOrderPreview(wxWindow *parent, const wxString title, const std::list<boss::Plugin>& plugins, const boss::Game& game) : wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) {
//Init controls.
_loadOrder = new wxListView(this, LIST_LoadOrder, wxDefaultPosition, wxDefaultSize, wxLC_REPORT);
//Populate list.
_loadOrder->AppendColumn(translate("Load Order"));
size_t i = 0;
for (list<boss::Plugin>::const_iterator it = plugins.begin(), endit = plugins.end(); it != endit; ++it, ++i) {
_loadOrder->InsertItem(i, FromUTF8(it->Name()));
if (it->FormIDs().empty()) {
_loadOrder->SetItemTextColour(i, wxColour(122, 122, 122));
}
else if (it->LoadsBSA(game)) {
_loadOrder->SetItemTextColour(i, wxColour(0, 142, 219));
}
}
_loadOrder->SetColumnWidth(0, wxLIST_AUTOSIZE);
//Set up layout.
wxBoxSizer * bigBox = new wxBoxSizer(wxVERTICAL);
bigBox->Add(_loadOrder, 1, wxEXPAND | wxALL, 15);
bigBox->Add(new wxStaticText(this, wxID_ANY, translate("Do you wish to make any changes to the load order above?")), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 15);
//Need to add 'Yes' and 'No' buttons.
wxSizer * sizer = CreateSeparatedButtonSizer(wxYES | wxNO | wxCANCEL);
//Now add buttons to window sizer.
if (sizer != NULL)
bigBox->Add(sizer, 0, wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT, 15);
//Now set the layout and sizes.
SetBackgroundColour(wxColour(255, 255, 255));
SetIcon(wxIconLocation("BOSS.exe"));
SetSizerAndFit(bigBox);
}
+66
View File
@@ -0,0 +1,66 @@
/* BOSS
A plugin load order optimiser for games that use the esp/esm plugin system.
Copyright (C) 2013-2014 WrinklyNinja
This file is part of BOSS.
BOSS is free software: you can redistribute
it and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
BOSS is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with BOSS. If not, see
<http://www.gnu.org/licenses/>.
*/
#ifndef __BOSS_GUI_SORTING__
#define __BOSS_GUI_SORTING__
#include "ids.h"
#include "../backend/metadata.h"
#include <string>
#include <vector>
#include <list>
#include <wx/spinctrl.h>
#include <wx/listctrl.h>
class MiniEditor : public wxDialog {
public:
MiniEditor(wxWindow *parent, const wxString& title, const std::vector<boss::Plugin>& plugins, const boss::Game& game);
void OnPluginSelect(wxListEvent& event);
void OnPluginListRightClick(wxListEvent& event);
void OnPluginCopy(wxCommandEvent& event);
void OnFilterToggle(wxCommandEvent& event);
void OnQuit(wxCommandEvent& event);
private:
wxButton * removeBtn;
wxButton * applyBtn;
wxButton * cancelBtn;
wxListView * pluginList;
wxListView * loadAfterList;
wxCheckBox * filterCheckbox;
wxSpinCtrl * prioritySpin;
wxStaticText * pluginText;
const std::vector<boss::Plugin>& _basePlugins;
std::list<boss::Plugin> _editedPlugins;
};
class LoadOrderPreview : public wxDialog {
public:
LoadOrderPreview(wxWindow *parent, const wxString title, const std::list<boss::Plugin>& plugins, const boss::Game& game);
private:
wxListView * _loadOrder;
};
#endif