Rewrite the toolbar generation code

The old toolbar code didn't actually support any nontrivial
customization of toolbars, as it had a hardcoded list of commands which
would be enabled or disabled, and the checks for enabling/disabling
toolbar buttons was done only in the specific situations which those
commands used.

Make icon size a user customizable option and add support for
dynamically changing it at runtime.

Originally committed to SVN as r5468.
This commit is contained in:
Thomas Goyne 2011-07-15 04:06:23 +00:00
parent f4d44f7c18
commit 88f0659307
10 changed files with 183 additions and 303 deletions

View File

@ -687,7 +687,6 @@ void BaseGrid::OnMouseEvent(wxMouseEvent &event) {
if (dlg == GetActiveLine()) {
SetActiveLine(GetDialogue(GetFirstSelRow()));
}
wxGetApp().frame->UpdateToolbar();
lastRow = row;
return;
}
@ -697,7 +696,6 @@ void BaseGrid::OnMouseEvent(wxMouseEvent &event) {
SetActiveLine(dlg);
if (dclick) context->videoController->JumpToTime(dlg->Start.GetMS());
SelectRow(row,false);
wxGetApp().frame->UpdateToolbar();
lastRow = row;
return;
}
@ -725,8 +723,6 @@ void BaseGrid::OnMouseEvent(wxMouseEvent &event) {
newsel.insert(GetDialogue(i));
}
SetSelectedSet(newsel);
wxGetApp().frame->UpdateToolbar();
}
return;
}

View File

@ -85,7 +85,6 @@
#include "video_slider.h"
enum {
ID_TOOLBAR_ZOOM_DROPDOWN = 11001,
ID_APP_TIMER_AUTOSAVE = 12001,
ID_APP_TIMER_STATUSCLEAR = 12002,
ID_MENU_AUTOMATION_MACRO = 13006,
@ -250,11 +249,8 @@ void FrameMain::cmd_call(wxCommandEvent& event) {
void FrameMain::InitToolbar () {
wxSystemOptions::SetOption("msw.remap", 0);
Toolbar = CreateToolBar(wxTB_FLAT | wxTB_HORIZONTAL,-1,"Toolbar");
toolbar::toolbar->GetToolbar("main", Toolbar);
Toolbar->Realize();
toolbar::AttachToolbar(this, "main", context.get());
GetToolBar()->Realize();
}
void FrameMain::InitMenu() {
@ -320,30 +316,6 @@ void FrameMain::InitContents() {
StartupLog("Leaving InitContents");
}
static void validate_toolbar(wxToolBar *toolbar, const char *command, const agi::Context *context) {
toolbar->FindById(cmd::id(command))->Enable(cmd::get(command)->Validate(context));
}
void FrameMain::UpdateToolbar() {
wxToolBar* toolbar = GetToolBar();
const agi::Context *c = context.get();
validate_toolbar(toolbar, "video/jump", c);
validate_toolbar(toolbar, "video/zoom/in", c);
validate_toolbar(toolbar, "video/zoom/out", c);
validate_toolbar(toolbar, "video/jump/start", c);
validate_toolbar(toolbar, "video/jump/end", c);
validate_toolbar(toolbar, "time/snap/start_video", c);
validate_toolbar(toolbar, "time/snap/end_video", c);
validate_toolbar(toolbar, "subtitle/select/visible", c);
validate_toolbar(toolbar, "time/snap/scene", c);
validate_toolbar(toolbar, "time/snap/frame", c);
toolbar->Realize();
}
void FrameMain::LoadSubtitles(wxString filename,wxString charset) {
if (context->ass->loaded) {
if (TryToCloseSubs() == wxCANCEL) return;
@ -427,7 +399,6 @@ void FrameMain::SetDisplayMode(int video, int audio) {
TopSizer->Show(videoBox, showVideo, true);
ToolsSizer->Show(audioSash, showAudio, true);
UpdateToolbar();
MainSizer->CalcMin();
MainSizer->RecalcSizes();
MainSizer->Layout();
@ -535,7 +506,6 @@ void FrameMain::DetachVideo(bool detach) {
context->detachedVideo = 0;
SetDisplayMode(1,-1);
}
UpdateToolbar();
}
void FrameMain::StatusTimeout(wxString text,int ms) {

View File

@ -107,7 +107,6 @@ private:
bool blockVideoLoad;
wxPanel *Panel;
wxToolBar *Toolbar; ///< The main toolbar
std::vector<Automation4::FeatureMacro*> activeMacroItems;
int AddMacroMenuItems(wxMenu *menu, const std::vector<Automation4::FeatureMacro*> &macros);
@ -160,7 +159,6 @@ public:
FrameMain(wxArrayString args);
~FrameMain();
void UpdateToolbar();
bool HasASSDraw();
DECLARE_EVENT_TABLE()

View File

@ -1,4 +1,4 @@
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org>
// Copyright (c) 2011, Thomas Goyne <plorkyeran@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@ -19,42 +19,16 @@
/// @ingroup menu toolbar
#ifndef AGI_PRE
#include <map>
#include <wx/toolbar.h>
#include <string>
#endif
#include <libaegisub/exception.h>
namespace json { class Array; }
namespace agi { struct Context; }
class wxFrame;
namespace toolbar {
DEFINE_BASE_EXCEPTION_NOINNER(ToolbarError, agi::Exception)
DEFINE_SIMPLE_EXCEPTION_NOINNER(ToolbarJsonValueArray, ToolbarError, "toolbar/value/array")
DEFINE_SIMPLE_EXCEPTION_NOINNER(ToolbarInvalidName, ToolbarError, "toolbar/invalid")
class Toolbar;
extern Toolbar *toolbar;
class Toolbar {
public:
Toolbar();
~Toolbar();
void GetToolbar(std::string name, wxToolBar *toolbar);
private:
typedef std::map<std::string, wxToolBar*> TbMap;
typedef std::pair<std::string, wxToolBar*> TbPair;
TbMap map;
enum ToolbarTypes {
Standard = 1,
Spacer = 100
};
void BuildToolbar(wxToolBar *toolbar, const json::Array& array);
};
} // namespace toolbar
/// Add the named toolbar to a window
/// @param frame Frame to attach the toolbar to
/// @param name Name of the toolbar
/// @param context Project context
void AttachToolbar(wxFrame *frame, std::string const& name, agi::Context *context);
}

View File

@ -14,7 +14,8 @@
"Maximized" : false,
"Nonstandard Milisecond Times" : false,
"Save Charset" : "UTF-8",
"Tips" : false
"Tips" : false,
"Toolbar Icon Size" : 16
},

View File

@ -1,140 +1,39 @@
{
"main" : [
{
"type" : 1,
"command" : "subtitle/new"
},
{
"type" : 1,
"command" : "subtitle/open"
},
{
"type" : 1,
"command" : "subtitle/save"
},
{
"type" : 100
},
{
"type" : 1,
"command" : "video/jump"
},
{
"type" : 1,
"command" : "video/zoom/in"
},
{
"type" : 1,
"command" : "video/zoom/out"
},
{
"type" : 1,
"command" : "video/jump/start"
},
{
"type" : 1,
"command" : "video/jump/end"
},
{
"type" : 100
},
{
"type" : 1,
"command" : "time/snap/start_video"
},
{
"type" : 1,
"command" : "time/snap/end_video"
},
{
"type" : 1,
"command" : "subtitle/select/visible"
},
{
"type" : 1,
"command" : "time/snap/scene"
},
{
"type" : 1,
"command" : "time/snap/frame"
},
{
"type" : 100
},
{
"type" : 1,
"command" : "tool/style/manager"
},
{
"type" : 1,
"command" : "subtitle/properties"
},
{
"type" : 1,
"command" : "subtitle/attachment"
},
{
"type" : 1,
"command" : "tool/font_collector"
},
{
"type" : 100
},
{
"type" : 1,
"command" : "am/manager"
},
{
"type" : 100
},
{
"type" : 1,
"command" : "tool/assdraw"
},
{
"type" : 100
},
{
"type" : 1,
"command" : "time/shift"
},
{
"type" : 1,
"command" : "tool/style/assistant"
},
{
"type" : 1,
"command" : "tool/translation_assistant"
},
{
"type" : 1,
"command" : "tool/resampleres"
},
{
"type" : 1,
"command" : "tool/time/postprocess"
},
{
"type" : 1,
"command" : "tool/time/kanji"
},
{
"type" : 1,
"command" : "subtitle/spellcheck"
},
{
"type" : 100
},
{
"type" : 1,
"command" : "app/options"
},
{
"type" : 1,
"command" : "grid/tag/cycle_hiding"
},
{
"type" : 100
}
]
"main" : [
"subtitle/new",
"subtitle/open",
"subtitle/save",
"",
"video/jump",
"video/zoom/in",
"video/zoom/out",
"video/jump/start",
"video/jump/end",
"",
"time/snap/start_video",
"time/snap/end_video",
"subtitle/select/visible",
"time/snap/scene",
"time/snap/frame",
"",
"tool/style/manager",
"subtitle/properties",
"subtitle/attachment",
"tool/font_collector",
"",
"am/manager",
"",
"tool/assdraw",
"",
"time/shift",
"tool/style/assistant",
"tool/translation_assistant",
"tool/resampleres",
"tool/time/postprocess",
"tool/time/kanji",
"subtitle/spellcheck",
"",
"app/options",
"grid/tag/cycle_hiding"
]
}

View File

@ -198,9 +198,6 @@ bool AegisubApp::OnInit() {
// Generate menus.
menu::menu = new menu::Menu();
// Generate toolbars.
toolbar::toolbar = new toolbar::Toolbar();
// Install assertion handler
// wxSetAssertHandler(wxAssertHandler);

View File

@ -44,9 +44,6 @@
#include "include/aegisub/subtitles_provider.h"
#include "video_provider_manager.h"
/// Define make all platform-specific options visible in a single view.
#define SHOW_ALL 1
#include "preferences_base.h"
/// General preferences page
@ -63,6 +60,9 @@ General::General(wxTreebook *book, Preferences *parent): OptionPage(book, parent
wxFlexGridSizer *undo = PageSizer(_("Undo / Redo Settings"));
OptionAdd(undo, _("Undo Levels"), "Limits/MRU");
wxFlexGridSizer *toolbar = PageSizer(_("Toolbar Settings"));
OptionAdd(toolbar, _("Toolbar Icon Size"), "App/Toolbar Icon Size");
SetSizerAndFit(sizer);
}
@ -335,7 +335,7 @@ Advanced_Audio::Advanced_Audio(wxTreebook *book, Preferences *parent): OptionPag
OptionAdd(spectrum, _("Cache memory max (MB)"), "Audio/Renderer/Spectrum/Memory Max", 2, 1024);
#if defined(WIN32) || defined(SHOW_ALL)
#if defined(WIN32) || defined(_DEBUG)
wxFlexGridSizer *windows = PageSizer(_("Windows Specific"));
const wxString adm_arr[3] = { _T("ConvertToMono"), _T("GetLeftChannel"), _T("GetRightChannel") };
wxArrayString adm_choice(3, adm_arr);
@ -357,7 +357,7 @@ Advanced_Video::Advanced_Video(wxTreebook *book, Preferences *parent): OptionPag
OptionChoice(expert, _("Subtitle provider"), sp_choice, "Subtitle/Provider");
#if defined(WIN32) || defined(SHOW_ALL)
#if defined(WIN32) || defined(_DEBUG)
wxFlexGridSizer *windows = PageSizer(_("Windows Specific"));
OptionAdd(windows, _("Allow pre-2.56a Avisynth"), "Provider/Avisynth/Allow Ancient");
CellSkip(windows);

View File

@ -1,4 +1,4 @@
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org>
// Copyright (c) 2011, Thomas Goyne <plorkyeran@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@ -20,81 +20,132 @@
#include "config.h"
#ifndef AGI_PRE
#include <math.h>
#include <memory>
#endif
#include <libaegisub/io.h>
#include <libaegisub/json.h>
#include <libaegisub/log.h>
#include "command/command.h"
#include "include/aegisub/context.h"
#include "include/aegisub/toolbar.h"
#include "libresrc/libresrc.h"
#include "command/command.h"
#include "main.h"
#ifndef AGI_PRE
#include <vector>
#include <wx/toolbar.h>
#endif
#include <libaegisub/json.h>
#include <libaegisub/signal.h>
namespace {
json::Object const& get_root() {
static json::Object root;
if (root.Empty()) {
root = agi::json_util::parse(new std::istringstream(GET_DEFAULT_CONFIG(default_toolbar)));
}
return root;
}
class Toolbar : public wxToolBar {
/// Window ID of first toolbar control
static const int TOOL_ID_BASE = 5000;
/// Toolbar name in config file
std::string name;
/// Project context
agi::Context *context;
/// Commands for each of the buttons
std::vector<cmd::Command *> commands;
/// Listener for icon size change signal
agi::signal::Connection icon_size_slot;
/// Enable/disable the toolbar buttons
void OnIdle(wxIdleEvent &) {
for (size_t i = 0; i < commands.size(); ++i) {
if (commands[i]->Type() & cmd::COMMAND_VALIDATE) {
EnableTool(TOOL_ID_BASE + i, commands[i]->Validate(context));
}
if (commands[i]->Type() & cmd::COMMAND_TOGGLE) {
ToggleTool(TOOL_ID_BASE + i, commands[i]->IsActive(context));
}
}
}
/// Toolbar button click handler
void OnClick(wxCommandEvent &evt) {
(*commands[evt.GetId() - TOOL_ID_BASE])(context);
}
/// Clear the toolbar and recreate it with the new icon size
void OnIconSizeChanged() {
Unbind(wxEVT_IDLE, &Toolbar::OnIdle, this);
ClearTools();
commands.clear();
Populate();
}
/// Populate the toolbar with buttons
void Populate() {
json::Object const& root = get_root();
json::Object::const_iterator it = root.Find(name);
if (it == root.End()) {
// Toolbar names are all hardcoded so this should never happen
throw agi::InternalError("Toolbar named " + name + " not found.", 0);
}
int icon_size = OPT_GET("App/Toolbar Icon Size")->GetInt();
json::Array arr = it->element;
commands.reserve(arr.Size());
bool needs_onidle = false;
for (json::Array::const_iterator it = arr.Begin(); it != arr.End(); ++it) {
json::String const& command_name = *it;
if (command_name.Value().empty()) {
AddSeparator();
}
else {
cmd::Command *command = cmd::get(command_name.Value());
wxBitmap *bitmap = command->Icon(icon_size);
// this hack is needed because ???
wxBitmap icon = bitmap->GetSubBitmap(wxRect(0, 0, bitmap->GetWidth(), bitmap->GetHeight()));
int flags = command->Type();
wxItemKind kind =
flags & cmd::COMMAND_RADIO ? wxITEM_RADIO :
flags & cmd::COMMAND_TOGGLE ? wxITEM_CHECK :
wxITEM_NORMAL;
AddTool(TOOL_ID_BASE + commands.size(), command->StrMenu(), icon, command->StrHelp(), kind);
commands.push_back(command);
needs_onidle = needs_onidle || flags != cmd::COMMAND_NORMAL;
}
}
// Only bind the update function if there are actually any dynamic tools
if (needs_onidle) {
Bind(wxEVT_IDLE, &Toolbar::OnIdle, this);
}
Realize();
}
public:
Toolbar(wxWindow *parent, std::string const& name, agi::Context *c)
: wxToolBar(parent, -1, wxDefaultPosition, wxDefaultSize, wxTB_FLAT | wxTB_HORIZONTAL)
, name(name)
, context(c)
, icon_size_slot(OPT_SUB("App/Toolbar Icon Size", &Toolbar::OnIconSizeChanged, this))
{
Populate();
Bind(wxEVT_COMMAND_TOOL_CLICKED, &Toolbar::OnClick, this);
}
};
}
namespace toolbar {
Toolbar *toolbar;
Toolbar::Toolbar() {}
Toolbar::~Toolbar() {}
void Toolbar::GetToolbar(std::string name, wxToolBar *toolbar) {
// TbMap::iterator index;
// if ((index = map.find(name)) != map.end()) {
// return index->second;
// }
// throw ToolbarInvalidName("Unknown index");
LOG_D("toolbar/init") << "Generating " << name << " toolbar.";
std::istringstream *stream = new std::istringstream(GET_DEFAULT_CONFIG(default_toolbar));
json::UnknownElement toolbar_root = agi::json_util::parse(stream);
const json::Array& arr = toolbar_root[name];
BuildToolbar(toolbar, arr);
// map.insert(TbPair(name, toolbar));
void AttachToolbar(wxFrame *frame, std::string const& name, agi::Context *c) {
frame->SetToolBar(new Toolbar(frame, name, c));
}
}
void Toolbar::BuildToolbar(wxToolBar *toolbar, const json::Array& array) {
for (json::Array::const_iterator index(array.Begin()); index != array.End(); index++) {
const json::Object& obj = *index;
int type = static_cast<json::Number>(obj["type"]).Value();
if (type == Toolbar::Spacer) {
toolbar->AddSeparator();
continue;
}
const json::String& command = obj["command"];
cmd::Command *cmd = cmd::get(command.Value());
// this is dumb.
wxBitmap *bitmap = cmd->Icon(24);
wxBitmap icon = bitmap->GetSubBitmap(wxRect(0, 0, bitmap->GetWidth(), bitmap->GetHeight()));
switch (type) {
case Toolbar::Standard: {
toolbar->AddTool(cmd::id(command.Value()), cmd->StrMenu(), icon, cmd->StrHelp(), wxITEM_NORMAL);
}
break;
}
} // for index
}
} // namespace toolbar

View File

@ -143,10 +143,8 @@ VideoDisplay::VideoDisplay(
{
assert(box);
if (zoomBox) {
zoomBox->SetValue(wxString::Format("%g%%", zoomValue * 100.));
zoomBox->Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &VideoDisplay::SetZoomFromBox, this);
}
zoomBox->SetValue(wxString::Format("%g%%", zoomValue * 100.));
zoomBox->Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &VideoDisplay::SetZoomFromBox, this);
box->Bind(wxEVT_COMMAND_TOOL_CLICKED, &VideoDisplay::OnMode, this, Video_Mode_Standard, Video_Mode_Vector_Clip);
con->videoController->Bind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this);
@ -170,9 +168,6 @@ VideoDisplay::VideoDisplay(
VideoDisplay::~VideoDisplay () {
con->videoController->Unbind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this);
if (zoomBox) {
zoomBox->Unbind(wxEVT_COMMAND_COMBOBOX_SELECTED, &VideoDisplay::SetZoomFromBox, this);
}
}
bool VideoDisplay::InitContext() {
@ -477,11 +472,10 @@ void VideoDisplay::OnKeyDown(wxKeyEvent &event) {
void VideoDisplay::SetZoom(double value) {
zoomValue = std::max(value, .125);
if (zoomBox) zoomBox->SetValue(wxString::Format("%g%%", zoomValue * 100.));
zoomBox->SetValue(wxString::Format("%g%%", zoomValue * 100.));
UpdateSize();
}
void VideoDisplay::SetZoomFromBox(wxCommandEvent &) {
if (!zoomBox) return;
wxString strValue = zoomBox->GetValue();
strValue.EndsWith(L"%", &strValue);
double value;