Пример #1
0
    //! Constructor.
    BasicRemoteOperation::BasicRemoteOperation(const std::string& name, Tasks::Context& ctx):
      Tasks::Periodic(name, ctx),
      m_connection(false),
      m_connection_timeout(1.0),
      m_last_action(-1.0),
      m_scope_ref(0)
    {
      // Define configuration parameters.
      paramActive(Tasks::Parameter::SCOPE_MANEUVER,
                  Tasks::Parameter::VISIBILITY_DEVELOPER,
                  false);

      param("Connection Timeout", m_connection_timeout)
      .defaultValue("1.0")
      .units(Units::Second);

      addActionButton("Exit");

      m_actions.op = IMC::RemoteActionsRequest::OP_REPORT;

      // Register handler routines.
      bind<IMC::Teleoperation>(this);
      bind<IMC::RemoteActions>(this);
      bind<IMC::RemoteActionsRequest>(this);
      bind<IMC::ControlLoops>(this);
    }
Пример #2
0
void gSampleChannel::update() {

	/* update sample button's label */

	switch (ch->status) {
		case STATUS_EMPTY:
			sampleButton->label("-- no sample --");
			break;
		case STATUS_MISSING:
		case STATUS_WRONG:
			sampleButton->label("* file not found! *");
			break;
		default:
			gu_trim_label(ch->wave->name.c_str(), 28, sampleButton);
			break;
	}

	/* update channels. If you load a patch with recorded actions, the 'R'
	 * button must be shown. Moreover if the actions are active, the 'R'
	 * button must be activated accordingly. */

	if (ch->hasActions)
		addActionButton();
	else
		delActionButton();

	/* update key box */

	char k[4];
	sprintf(k, "%c", ch->key);
	button->copy_label(k);
	button->redraw();

	/* updates modebox */

	modeBox->value(ch->mode);
	modeBox->redraw();

	/* update volumes+mute+solo */

	vol->value(ch->volume);
	mute->value(ch->mute);
	solo->value(ch->solo);
}
Пример #3
0
void gSampleChannel::update()
{
	

	switch (ch->status) {
		case STATUS_EMPTY:
			mainButton->label("-- no sample --");
			break;
		case STATUS_MISSING:
		case STATUS_WRONG:
			mainButton->label("* file not found! *");
			break;
		default:
			mainButton->label(ch->wave->name.c_str());
			break;
	}

	

	if (ch->hasActions)
		addActionButton();
	else
		delActionButton();

	

	modeBox->value(ch->mode);
	modeBox->redraw();

	

	vol->value(ch->volume);
	mute->value(ch->mute);
	solo->value(ch->solo);

	mainButton->setKey(ch->key);

#ifdef WITH_VST
	fx->full = ch->plugins_DEPR_.size() > 0;
	fx->redraw();
#endif
}
Пример #4
0
    //! Constructor.
    BasicRemoteOperation::BasicRemoteOperation(const std::string& name, Tasks::Context& ctx):
      Tasks::Periodic(name, ctx),
      m_connection(false),
      m_connection_timeout(1.0),
      m_last_action(-1.0)
    {
      param("Connection Timeout", m_connection_timeout)
      .defaultValue("1.0")
      .units(Units::Second);

      addActionButton("Exit");

      m_actions.op = IMC::RemoteActionsRequest::OP_REPORT;

      deactivate();

      // Register handler routines.
      bind<IMC::RemoteActions>(this);
      bind<IMC::RemoteActionsRequest>(this);
      bind<IMC::ControlLoops>(this);
    }
Пример #5
0
GerritDialog::GerritDialog(const QSharedPointer<GerritParameters> &p,
                           const QSharedPointer<GerritServer> &s,
                           const QString &repository,
                           QWidget *parent)
    : QDialog(parent)
    , m_parameters(p)
    , m_server(s)
    , m_filterModel(new QSortFilterProxyModel(this))
    , m_ui(new Ui::GerritDialog)
    , m_model(new GerritModel(p, this))
    , m_queryModel(new QStringListModel(this))
{
    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);

    m_ui->setupUi(this);
    m_ui->remoteComboBox->setParameters(m_parameters);
    m_ui->remoteComboBox->setFallbackEnabled(true);
    m_queryModel->setStringList(m_parameters->savedQueries);
    QCompleter *completer = new QCompleter(this);
    completer->setModel(m_queryModel);
    m_ui->queryLineEdit->setSpecialCompleter(completer);
    m_ui->queryLineEdit->setOkColor(Utils::creatorTheme()->color(Utils::Theme::TextColorNormal));
    m_ui->queryLineEdit->setErrorColor(Utils::creatorTheme()->color(Utils::Theme::TextColorError));
    m_ui->queryLineEdit->setValidationFunction([this](Utils::FancyLineEdit *, QString *) {
                                               return m_model->state() != GerritModel::Error;
                                           });
    m_ui->filterLineEdit->setFiltering(true);
    connect(m_ui->filterLineEdit, &Utils::FancyLineEdit::filterChanged,
            m_filterModel, &QSortFilterProxyModel::setFilterFixedString);
    connect(m_ui->queryLineEdit, &QLineEdit::returnPressed, this, &GerritDialog::refresh);
    connect(m_model, &GerritModel::stateChanged, m_ui->queryLineEdit, &Utils::FancyLineEdit::validate);
    connect(m_ui->remoteComboBox, &GerritRemoteChooser::remoteChanged,
            this, &GerritDialog::remoteChanged);
    m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
    m_filterModel->setSourceModel(m_model);
    m_filterModel->setFilterRole(GerritModel::FilterRole);
    m_filterModel->setSortRole(GerritModel::SortRole);
    m_ui->treeView->setModel(m_filterModel);
    m_ui->treeView->setActivationMode(Utils::DoubleClickActivation);

    connect(&m_progressIndicatorTimer, &QTimer::timeout,
            [this]() { setProgressIndicatorVisible(true); });
    m_progressIndicatorTimer.setSingleShot(true);
    m_progressIndicatorTimer.setInterval(50); // don't show progress for < 50ms tasks

    m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Large,
                                                       m_ui->treeView);
    m_progressIndicator->attachToWidget(m_ui->treeView->viewport());
    m_progressIndicator->hide();

    connect(m_model, &GerritModel::stateChanged, this, &GerritDialog::manageProgressIndicator);

    QItemSelectionModel *selectionModel = m_ui->treeView->selectionModel();
    connect(selectionModel, &QItemSelectionModel::currentChanged,
            this, &GerritDialog::slotCurrentChanged);
    connect(m_ui->treeView, &QAbstractItemView::activated,
            this, &GerritDialog::slotActivated);

    m_displayButton = addActionButton(tr("&Show"), [this]() { slotFetchDisplay(); });
    m_cherryPickButton = addActionButton(tr("Cherry &Pick"), [this]() { slotFetchCherryPick(); });
    m_checkoutButton = addActionButton(tr("C&heckout"), [this]() { slotFetchCheckout(); });
    m_refreshButton = addActionButton(tr("&Refresh"), [this]() { refresh(); });

    connect(m_model, &GerritModel::refreshStateChanged,
            m_refreshButton, &QWidget::setDisabled);
    connect(m_model, &GerritModel::refreshStateChanged,
            this, &GerritDialog::slotRefreshStateChanged);
    connect(m_model, &GerritModel::errorText,
            this, [this](const QString &text) {
        if (text.contains("returned error: 401"))
            updateRemotes(true);
    }, Qt::QueuedConnection);

    setCurrentPath(repository);
    slotCurrentChanged();

    m_ui->treeView->setFocus();
    m_refreshButton->setDefault(true);
}
Пример #6
0
// -----------------------------------------------------------------------------
// Sets up the wxWidgets window layout
// -----------------------------------------------------------------------------
void MainWindow::setupLayout()
{
	// Create the wxAUI manager & related things
	aui_mgr_ = new wxAuiManager(this);
	aui_mgr_->SetArtProvider(new SAuiDockArt());
	wxAuiPaneInfo p_inf;

	// Set icon
	auto icon_filename = App::path(App::iconFile(), App::Dir::Temp);
	App::archiveManager().programResourceArchive()->entry(App::iconFile())->exportFile(icon_filename);
	SetIcon(wxIcon(icon_filename, wxBITMAP_TYPE_ICO));
	wxRemoveFile(icon_filename);


	// -- Editor Area --
	stc_tabs_ = new STabCtrl(this, true, true, tabs_condensed ? 27 : 31, true, true);

	// Setup panel info & add panel
	p_inf.CenterPane();
	p_inf.Name("editor_area");
	p_inf.PaneBorder(false);
	aui_mgr_->AddPane(stc_tabs_, p_inf);

	// Create Start Page
	start_page_ = new SStartPage(stc_tabs_);
	if (show_start_page)
	{
		stc_tabs_->AddPage(start_page_, "Start Page");
		stc_tabs_->SetPageBitmap(0, Icons::getIcon(Icons::General, "logo"));
		start_page_->init();
		createStartPage();
	}
	else
		start_page_->Show(false);

	// -- Console Panel --
	auto panel_console = new ConsolePanel(this, -1);

	// Setup panel info & add panel
	p_inf.DefaultPane();
	p_inf.Float();
	p_inf.FloatingSize(WxUtils::scaledSize(600, 400));
	p_inf.FloatingPosition(WxUtils::scaledPoint(100, 100));
	p_inf.MinSize(WxUtils::scaledSize(-1, 192));
	p_inf.Show(false);
	p_inf.Caption("Console");
	p_inf.Name("console");
	aui_mgr_->AddPane(panel_console, p_inf);


	// -- Archive Manager Panel --
	panel_archivemanager_ = new ArchiveManagerPanel(this, stc_tabs_);

	// Setup panel info & add panel
	p_inf.DefaultPane();
	p_inf.Left();
	p_inf.BestSize(WxUtils::scaledSize(192, 480));
	p_inf.Caption("Archive Manager");
	p_inf.Name("archive_manager");
	p_inf.Show(true);
	p_inf.Dock();
	aui_mgr_->AddPane(panel_archivemanager_, p_inf);


	// -- Undo History Panel --
	panel_undo_history_ = new UndoManagerHistoryPanel(this, nullptr);

	// Setup panel info & add panel
	p_inf.DefaultPane();
	p_inf.Right();
	p_inf.BestSize(WxUtils::scaledSize(128, 480));
	p_inf.Caption("Undo History");
	p_inf.Name("undo_history");
	p_inf.Show(false);
	p_inf.Dock();
	aui_mgr_->AddPane(panel_undo_history_, p_inf);


	// -- Menu bar --
	auto menu = new wxMenuBar();
	menu->SetThemeEnabled(false);

	// File menu
	auto file_new_menu = new wxMenu("");
	SAction::fromId("aman_newwad")->addToMenu(file_new_menu, "&Wad Archive");
	SAction::fromId("aman_newzip")->addToMenu(file_new_menu, "&Zip Archive");
	SAction::fromId("aman_newmap")->addToMenu(file_new_menu, "&Map");
	auto file_menu = new wxMenu("");
	file_menu->AppendSubMenu(file_new_menu, "&New", "Create a new Archive");
	SAction::fromId("aman_open")->addToMenu(file_menu);
	SAction::fromId("aman_opendir")->addToMenu(file_menu);
	file_menu->AppendSeparator();
	SAction::fromId("aman_save")->addToMenu(file_menu);
	SAction::fromId("aman_saveas")->addToMenu(file_menu);
	SAction::fromId("aman_saveall")->addToMenu(file_menu);
	file_menu->AppendSubMenu(panel_archivemanager_->getRecentMenu(), "&Recent Files");
	file_menu->AppendSeparator();
	SAction::fromId("aman_close")->addToMenu(file_menu);
	SAction::fromId("aman_closeall")->addToMenu(file_menu);
	file_menu->AppendSeparator();
	SAction::fromId("main_exit")->addToMenu(file_menu);
	menu->Append(file_menu, "&File");

	// Edit menu
	auto editor_menu = new wxMenu("");
	SAction::fromId("main_undo")->addToMenu(editor_menu);
	SAction::fromId("main_redo")->addToMenu(editor_menu);
	editor_menu->AppendSeparator();
	SAction::fromId("main_setbra")->addToMenu(editor_menu);
	SAction::fromId("main_preferences")->addToMenu(editor_menu);
	menu->Append(editor_menu, "E&dit");

	// View menu
	auto view_menu = new wxMenu("");
	SAction::fromId("main_showam")->addToMenu(view_menu);
	SAction::fromId("main_showconsole")->addToMenu(view_menu);
	SAction::fromId("main_showundohistory")->addToMenu(view_menu);
	SAction::fromId("main_showstartpage")->addToMenu(view_menu);
	toolbar_menu_ = new wxMenu();
	view_menu->AppendSubMenu(toolbar_menu_, "Toolbars");
	menu->Append(view_menu, "&View");

	// Tools menu
	auto tools_menu = new wxMenu("");
	SAction::fromId("main_runscript")->addToMenu(tools_menu);
	menu->Append(tools_menu, "&Tools");

	// Help menu
	auto help_menu = new wxMenu("");
	SAction::fromId("main_onlinedocs")->addToMenu(help_menu);
	SAction::fromId("main_about")->addToMenu(help_menu);
#ifdef __WXMSW__
	SAction::fromId("main_updatecheck")->addToMenu(help_menu);
#endif
	menu->Append(help_menu, "&Help");

	// Set the menu
	SetMenuBar(menu);



	// -- Toolbars --
	toolbar_ = new SToolBar(this, true);

	// Create File toolbar
	auto tbg_file = new SToolBarGroup(toolbar_, "_File");
	tbg_file->addActionButton("aman_newwad");
	tbg_file->addActionButton("aman_newzip");
	tbg_file->addActionButton("aman_open");
	tbg_file->addActionButton("aman_opendir");
	tbg_file->addActionButton("aman_save");
	tbg_file->addActionButton("aman_saveas");
	tbg_file->addActionButton("aman_saveall");
	tbg_file->addActionButton("aman_close");
	tbg_file->addActionButton("aman_closeall");
	toolbar_->addGroup(tbg_file);

	// Create Archive toolbar
	auto tbg_archive = new SToolBarGroup(toolbar_, "_Archive");
	tbg_archive->addActionButton("arch_newentry");
	tbg_archive->addActionButton("arch_newdir");
	tbg_archive->addActionButton("arch_importfiles");
	tbg_archive->addActionButton("arch_texeditor");
	tbg_archive->addActionButton("arch_mapeditor");
	tbg_archive->addActionButton("arch_run");
	toolbar_->addGroup(tbg_archive);

	// Create Entry toolbar
	auto tbg_entry = new SToolBarGroup(toolbar_, "_Entry");
	tbg_entry->addActionButton("arch_entry_rename");
	tbg_entry->addActionButton("arch_entry_delete");
	tbg_entry->addActionButton("arch_entry_import");
	tbg_entry->addActionButton("arch_entry_export");
	tbg_entry->addActionButton("arch_entry_moveup");
	tbg_entry->addActionButton("arch_entry_movedown");
	toolbar_->addGroup(tbg_entry);

	// Create Base Resource Archive toolbar
	auto tbg_bra = new SToolBarGroup(toolbar_, "_Base Resource", true);
	auto brc     = new BaseResourceChooser(tbg_bra);
	tbg_bra->addCustomControl(brc);
	tbg_bra->addActionButton("main_setbra", "settings");
	toolbar_->addGroup(tbg_bra);

	// Create Palette Chooser toolbar
	auto tbg_palette = new SToolBarGroup(toolbar_, "_Palette", true);
	palette_chooser_ = new PaletteChooser(tbg_palette, -1);
	palette_chooser_->selectPalette(global_palette);
	tbg_palette->addCustomControl(palette_chooser_);
	toolbar_->addGroup(tbg_palette);

	// Archive and Entry toolbars are initially disabled
	toolbar_->enableGroup("_archive", false);
	toolbar_->enableGroup("_entry", false);

	// Add toolbar
	aui_mgr_->AddPane(
		toolbar_,
		wxAuiPaneInfo()
			.Top()
			.CaptionVisible(false)
			.MinSize(-1, SToolBar::getBarHeight())
			.Resizable(false)
			.PaneBorder(false)
			.Name("toolbar"));

	// Populate the 'View->Toolbars' menu
	populateToolbarsMenu();
	toolbar_->enableContextMenu();

	// -- Status Bar --
	CreateStatusBar(3);


	// Load previously saved perspective string
	loadLayout();

	// Finalize
	aui_mgr_->Update();
	Layout();

	// Bind events
	Bind(wxEVT_SIZE, &MainWindow::onSize, this);
	Bind(wxEVT_CLOSE_WINDOW, &MainWindow::onClose, this);
	Bind(wxEVT_AUINOTEBOOK_PAGE_CHANGED, &MainWindow::onTabChanged, this);
	Bind(wxEVT_STOOLBAR_LAYOUT_UPDATED, &MainWindow::onToolBarLayoutChanged, this, toolbar_->GetId());
	Bind(wxEVT_ACTIVATE, &MainWindow::onActivate, this);
	Bind(wxEVT_AUINOTEBOOK_PAGE_CLOSE, [&](wxAuiNotebookEvent& e) {
		// Null start_page pointer if start page tab is closed
		auto page = stc_tabs_->GetPage(stc_tabs_->GetSelection());
		if (page->GetName() == "startpage")
			start_page_ = nullptr;
	});

	// Initial focus to toolbar
	toolbar_->SetFocus();
}
Пример #7
0
GerritDialog::GerritDialog(const QSharedPointer<GerritParameters> &p,
                           QWidget *parent)
    : QDialog(parent)
    , m_parameters(p)
    , m_filterModel(new QSortFilterProxyModel(this))
    , m_model(new GerritModel(p, this))
    , m_queryModel(new QStringListModel(this))
    , m_treeView(new Utils::TreeView)
    , m_detailsBrowser(new QTextBrowser)
    , m_queryLineEdit(new Utils::FancyLineEdit)
    , m_filterLineEdit(new Utils::FancyLineEdit)
    , m_repositoryChooser(new Utils::PathChooser)
    , m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Close))
    , m_repositoryChooserLabel(new QLabel(tr("Apply in:") + QLatin1Char(' '), this))
    , m_fetchRunning(false)
{
    setWindowTitle(tr("Gerrit %1@%2").arg(p->user, p->host));
    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);

    QGroupBox *changesGroup = new QGroupBox(tr("Changes"));
    QVBoxLayout *changesLayout = new QVBoxLayout(changesGroup);
    changesLayout->setMargin(layoutSpacing);
    QHBoxLayout *filterLayout = new QHBoxLayout;
    QLabel *queryLabel = new QLabel(tr("&Query:"));
    queryLabel->setBuddy(m_queryLineEdit);
    m_queryLineEdit->setFixedWidth(400);
    m_queryLineEdit->setPlaceholderText(tr("Change #, SHA-1, tr:id, owner:email or reviewer:email"));
    m_queryModel->setStringList(m_parameters->savedQueries);
    QCompleter *completer = new QCompleter(this);
    completer->setModel(m_queryModel);
    m_queryLineEdit->setSpecialCompleter(completer);
    m_queryLineEdit->setOkColor(Utils::creatorTheme()->color(Utils::Theme::TextColorNormal));
    m_queryLineEdit->setErrorColor(Utils::creatorTheme()->color(Utils::Theme::TextColorError));
    m_queryLineEdit->setValidationFunction([this](Utils::FancyLineEdit *, QString *) {
                                               return m_model->state() != GerritModel::Error;
                                           });
    filterLayout->addWidget(queryLabel);
    filterLayout->addWidget(m_queryLineEdit);
    filterLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
    m_filterLineEdit->setFixedWidth(300);
    m_filterLineEdit->setFiltering(true);
    filterLayout->addWidget(m_filterLineEdit);
    connect(m_filterLineEdit, &Utils::FancyLineEdit::filterChanged,
            m_filterModel, &QSortFilterProxyModel::setFilterFixedString);
    connect(m_queryLineEdit, &QLineEdit::returnPressed, this, &GerritDialog::slotRefresh);
    connect(m_model, &GerritModel::stateChanged, m_queryLineEdit, &Utils::FancyLineEdit::validate);
    m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
    changesLayout->addLayout(filterLayout);
    changesLayout->addWidget(m_treeView);

    m_filterModel->setSourceModel(m_model);
    m_filterModel->setFilterRole(GerritModel::FilterRole);
    m_filterModel->setSortRole(GerritModel::SortRole);
    m_treeView->setRootIsDecorated(true);
    m_treeView->setModel(m_filterModel);
    m_treeView->setMinimumWidth(600);
    m_treeView->setUniformRowHeights(true);
    m_treeView->setRootIsDecorated(false);
    m_treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
    m_treeView->setSortingEnabled(true);
    m_treeView->setActivationMode(Utils::DoubleClickActivation);

    connect(&m_progressIndicatorTimer, &QTimer::timeout,
            [this]() { setProgressIndicatorVisible(true); });
    m_progressIndicatorTimer.setSingleShot(true);
    m_progressIndicatorTimer.setInterval(50); // don't show progress for < 50ms tasks

    m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicator::Large,
                                                       m_treeView);
    m_progressIndicator->attachToWidget(m_treeView->viewport());
    m_progressIndicator->hide();

    connect(m_model, &GerritModel::stateChanged, this, &GerritDialog::manageProgressIndicator);

    QItemSelectionModel *selectionModel = m_treeView->selectionModel();
    connect(selectionModel, &QItemSelectionModel::currentChanged,
            this, &GerritDialog::slotCurrentChanged);
    connect(m_treeView, &QAbstractItemView::activated,
            this, &GerritDialog::slotActivated);

    QGroupBox *detailsGroup = new QGroupBox(tr("Details"));
    QVBoxLayout *detailsLayout = new QVBoxLayout(detailsGroup);
    detailsLayout->setMargin(layoutSpacing);
    m_detailsBrowser->setOpenExternalLinks(true);
    m_detailsBrowser->setTextInteractionFlags(Qt::TextBrowserInteraction);
    detailsLayout->addWidget(m_detailsBrowser);

    m_repositoryChooser->setExpectedKind(Utils::PathChooser::Directory);
    m_repositoryChooser->setHistoryCompleter(QLatin1String("Git.RepoDir.History"));
    QHBoxLayout *repoPathLayout = new QHBoxLayout;
    repoPathLayout->addWidget(m_repositoryChooserLabel);
    repoPathLayout->addWidget(m_repositoryChooser);
    detailsLayout->addLayout(repoPathLayout);

    m_displayButton = addActionButton(tr("&Show"), [this]() { slotFetchDisplay(); });
    m_cherryPickButton = addActionButton(tr("Cherry &Pick"), [this]() { slotFetchCherryPick(); });
    m_checkoutButton = addActionButton(tr("C&heckout"), [this]() { slotFetchCheckout(); });
    m_refreshButton = addActionButton(tr("&Refresh"), [this]() { slotRefresh(); });

    connect(m_model, &GerritModel::refreshStateChanged,
            m_refreshButton, &QWidget::setDisabled);
    connect(m_model, &GerritModel::refreshStateChanged,
            this, &GerritDialog::slotRefreshStateChanged);
    connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
    connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);

    QSplitter *splitter = new QSplitter(Qt::Vertical, this);
    splitter->addWidget(changesGroup);
    splitter->addWidget(detailsGroup);
    splitter->setSizes(QList<int>() <<  400 << 200);

    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(splitter);
    mainLayout->addWidget(m_buttonBox);

    slotCurrentChanged();
    slotRefresh();

    resize(QSize(950, 600));
    m_treeView->setFocus();
    m_refreshButton->setDefault(true);
}
Пример #8
0
// -----------------------------------------------------------------------------
// Adds controls to the entry panel toolbar
// -----------------------------------------------------------------------------
void GfxEntryPanel::setupToolbar()
{
	// Zoom
	auto g_zoom  = new SToolBarGroup(toolbar_, "Zoom");
	slider_zoom_ = new SZoomSlider(g_zoom, gfx_canvas_);
	g_zoom->addCustomControl(slider_zoom_);
	toolbar_->addGroup(g_zoom);

	// Editing operations
	auto g_edit = new SToolBarGroup(toolbar_, "Editing");
	g_edit->addActionButton("pgfx_settrans", "");
	cb_colour_ = new ColourBox(g_edit, -1, ColRGBA::BLACK, false, true);
	cb_colour_->setPalette(&gfx_canvas_->palette());
	button_brush_ = g_edit->addActionButton("pgfx_setbrush", "");
	g_edit->addCustomControl(cb_colour_);
	g_edit->addActionButton("pgfx_drag", "");
	g_edit->addActionButton("pgfx_draw", "");
	g_edit->addActionButton("pgfx_erase", "");
	g_edit->addActionButton("pgfx_magic", "");
	SAction::fromId("pgfx_drag")->setChecked(); // Drag offsets by default
	toolbar_->addGroup(g_edit);

	// Image operations
	auto g_image = new SToolBarGroup(toolbar_, "Image");
	g_image->addActionButton("pgfx_mirror", "");
	g_image->addActionButton("pgfx_flip", "");
	g_image->addActionButton("pgfx_rotate", "");
	g_image->addActionButton("pgfx_crop", "");
	g_image->addActionButton("pgfx_convert", "");
	toolbar_->addGroup(g_image);

	// Colour operations
	auto g_colour = new SToolBarGroup(toolbar_, "Colour");
	g_colour->addActionButton("pgfx_remap", "");
	g_colour->addActionButton("pgfx_colourise", "");
	g_colour->addActionButton("pgfx_tint", "");
	toolbar_->addGroup(g_colour);

	// Misc operations
	auto g_png = new SToolBarGroup(toolbar_, "PNG");
	g_png->addActionButton("pgfx_pngopt", "");
	toolbar_->addGroup(g_png);
	toolbar_->enableGroup("PNG", false);
}