예제 #1
0
void add_wml_hotkey(const std::string& id, const t_string& description, const config& default_hotkey)
{
	if(id == "null")
	{
		LOG_G << "Couldn't add wml hotkey with null id and description = '" << description << "'.\n";
		return;
	}
	else
	{
		if(has_hotkey_command(id))
		{
			LOG_G << "Hotkey with id '" << id << "' already exists. Deleting the old hotkey_command.\n";
			remove_wml_hotkey(id);
		}
		DBG_G << "Added wml hotkey with id = '" << id << "' and description = '" << description << "'.\n";
		known_hotkeys.push_back(new hotkey_command(hotkey::HOTKEY_WML, id, description, false, hotkey::SCOPE_GAME, t_string("")));

		command_map_[id] = known_hotkeys.size() - 1;

		if(!default_hotkey.empty() && !has_hotkey_item(id))
		{
			hotkey_item new_item(default_hotkey, true);
			new_item.set_command(id);
			if(new_item.valid())
			{
				DBG_G << "added default description for the wml hotkey with id=" + id;
				add_hotkey(new_item);
			}
			else
			{
				ERR_CF << "failed to add default hotkey with id=" + id;
			}
		}
	}
}
예제 #2
0
HotKeysParser::HotKeysParser(const std::string& hotkeys, const CommandsMap& commands_map)
{
    DBG(0, "hotkeys = %s", hotkeys.c_str());

    std::istringstream is(hotkeys);
    std::string hotkey;
    while (std::getline(is, hotkey, ',')) {
        add_hotkey(hotkey, commands_map);
    }
}
void hotkey_button_pressed(int n)
{
	switch (n) {
		case SCROLL_UP_BUTTON:
			hotkey_scroll_screen_up();
			break;

		case SCROLL_DOWN_BUTTON:
			hotkey_scroll_screen_down();
			break;

		case ADD_HOTKEY_BUTTON:
			add_hotkey(Cur_hotkey);
			gamesnd_play_iface(SND_USER_SELECT);
			break;

		case REMOVE_HOTKEY_BUTTON:
			remove_hotkey();
			gamesnd_play_iface(SND_USER_SELECT);
			break;

		case ACCEPT_BUTTON:
			save_hotkeys();
			// fall through to CANCEL_BUTTON

		case CANCEL_BUTTON:			
			mission_hotkey_exit();
			gamesnd_play_iface(SND_USER_SELECT);
			break;

		case HELP_BUTTON:
			launch_context_help();
			gamesnd_play_iface(SND_HELP_PRESSED);
			break;

		case OPTIONS_BUTTON:			
			gameseq_post_event(GS_EVENT_OPTIONS_MENU);
			gamesnd_play_iface(SND_USER_SELECT);
			break;

		case CLEAR_BUTTON:
			clear_hotkeys();
			gamesnd_play_iface(SND_USER_SELECT);
			break;

		case RESET_BUTTON:
			reset_hotkeys();
			gamesnd_play_iface(SND_USER_SELECT);
			break;
	}
}
예제 #4
0
void load_hotkeys(const config& cfg, bool set_as_default)
{
	for (const config &hk : cfg.child_range("hotkey")) {

		hotkey_ptr item = load_from_config(hk);
		if (!set_as_default) {
			item->unset_default();
		}

		if (!item->null()) {
			add_hotkey(item);
		}
	}

	if (set_as_default) {
		default_hotkey_cfg_ = cfg;
	}
}
예제 #5
0
void load_defaults (void)
{
    HotkeyConfiguration* hotkey;

    hotkey = &(plugin_cfg.first);

    add_hotkey(&hotkey, XF86XK_AudioPrev, 0, TYPE_KEY, EVENT_PREV_TRACK);
    add_hotkey(&hotkey, XF86XK_AudioPlay, 0, TYPE_KEY, EVENT_PLAY);
    add_hotkey(&hotkey, XF86XK_AudioPause, 0, TYPE_KEY, EVENT_PAUSE);
    add_hotkey(&hotkey, XF86XK_AudioStop, 0, TYPE_KEY, EVENT_STOP);
    add_hotkey(&hotkey, XF86XK_AudioNext, 0, TYPE_KEY, EVENT_NEXT_TRACK);

/*    add_hotkey(&hotkey, XF86XK_AudioRewind, 0, TYPE_KEY, EVENT_BACKWARD); */

    add_hotkey(&hotkey, XF86XK_AudioMute, 0, TYPE_KEY, EVENT_MUTE);
    add_hotkey(&hotkey, XF86XK_AudioRaiseVolume, 0, TYPE_KEY, EVENT_VOL_UP);
    add_hotkey(&hotkey, XF86XK_AudioLowerVolume, 0, TYPE_KEY, EVENT_VOL_DOWN);

/*    add_hotkey(&hotkey, XF86XK_AudioMedia, 0, TYPE_KEY, EVENT_JUMP_TO_FILE);
    add_hotkey(&hotkey, XF86XK_Music, 0, TYPE_KEY, EVENT_TOGGLE_WIN); */
}
예제 #6
0
DialogStyling::DialogStyling(agi::Context *context)
: wxDialog(context->parent, -1, _("Styling Assistant"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX)
, c(context)
, active_line_connection(context->selectionController->AddActiveLineListener(&DialogStyling::OnActiveLineChanged, this))
, active_line(0)
{
	SetIcon(GETICON(styling_toolbutton_16));

	wxSizer *main_sizer = new wxBoxSizer(wxVERTICAL);
	wxSizer *bottom_sizer = new wxBoxSizer(wxHORIZONTAL);

	{
		wxSizer *cur_line_box = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Current line"));
		current_line_text = new wxTextCtrl(this, -1, _("Current line"), wxDefaultPosition, wxSize(300, 60), wxTE_MULTILINE | wxTE_READONLY);
		cur_line_box->Add(current_line_text, 1, wxEXPAND, 0);
		main_sizer->Add(cur_line_box, 0, wxEXPAND | wxALL, 5);
	}

	{
		wxSizer *styles_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Styles available"));
		style_list = new wxListBox(this, -1, wxDefaultPosition, wxSize(150, 180), context->ass->GetStyles());
		styles_box->Add(style_list, 1, wxEXPAND, 0);
		bottom_sizer->Add(styles_box, 1, wxEXPAND | wxRIGHT, 5);
	}

	wxSizer *right_sizer = new wxBoxSizer(wxVERTICAL);
	{
		wxSizer *style_text_box = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Set style"));
		style_name = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxSize(180, -1), wxTE_PROCESS_ENTER);
		style_text_box->Add(style_name, 1, wxEXPAND);
		right_sizer->Add(style_text_box, 0, wxEXPAND | wxBOTTOM, 5);
	}

	{
		wxSizer *hotkey_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Keys"));

		wxSizer *hotkey_grid = new wxGridSizer(2, 0, 5);
		add_hotkey(hotkey_grid, this, "tool/styling_assistant/commit", _("Accept changes"));
		add_hotkey(hotkey_grid, this, "tool/styling_assistant/preview", _("Preview changes"));
		add_hotkey(hotkey_grid, this, "grid/line/prev", _("Previous line"));
		add_hotkey(hotkey_grid, this, "grid/line/next", _("Next line"));
		add_hotkey(hotkey_grid, this, "video/play/line", _("Play video"));
		add_hotkey(hotkey_grid, this, "audio/play/selection", _("Play audio"));
		hotkey_grid->Add(new wxStaticText(this, -1, _("Click on list")));
		hotkey_grid->Add(new wxStaticText(this, -1, _("Select style")));

		hotkey_box->Add(hotkey_grid, 0, wxEXPAND | wxBOTTOM, 5);

		auto_seek = new wxCheckBox(this, -1, _("&Seek video to line start time"));
		auto_seek->SetValue(true);
		hotkey_box->Add(auto_seek, 0, 0, 0);
		hotkey_box->AddStretchSpacer(1);

		right_sizer->Add(hotkey_box, 0, wxEXPAND | wxBOTTOM, 5);
	}

	{
		wxSizer *actions_box = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Actions"));
		actions_box->AddStretchSpacer(1);

		play_audio = new wxButton(this, -1, _("Play &Audio"));
		play_audio->Enable(c->audioController->IsAudioOpen());
		actions_box->Add(play_audio, 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);

		play_video = new wxButton(this, -1, _("Play &Video"));
		play_video->Enable(c->videoController->IsLoaded());
		actions_box->Add(play_video, 0, wxBOTTOM | wxRIGHT, 5);

		actions_box->AddStretchSpacer(1);
		right_sizer->Add(actions_box, 0, wxEXPAND, 5);
	}
	bottom_sizer->Add(right_sizer);
	main_sizer->Add(bottom_sizer, 1, wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT, 5);

	{
		wxStdDialogButtonSizer *button_sizer = new wxStdDialogButtonSizer;
		button_sizer->AddButton(new wxButton(this, wxID_CANCEL));
		button_sizer->AddButton(new HelpButton(this, "Styling Assistant"));
		button_sizer->Realize();

		main_sizer->Add(button_sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 5);
	}

	SetSizerAndFit(main_sizer);

	persist.reset(new PersistLocation(this, "Tool/Styling Assistant"));

	Bind(wxEVT_ACTIVATE, &DialogStyling::OnActivate, this);
	Bind(wxEVT_CHAR_HOOK, &DialogStyling::OnCharHook, this);
	style_name->Bind(wxEVT_CHAR_HOOK, &DialogStyling::OnCharHook, this);
	style_name->Bind(wxEVT_KEY_DOWN, &DialogStyling::OnKeyDown, this);
	play_video->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogStyling::OnPlayVideoButton, this);
	play_audio->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogStyling::OnPlayAudioButton, this);
	style_list->Bind(wxEVT_COMMAND_LISTBOX_SELECTED, &DialogStyling::OnListClicked, this);
	style_list->Bind(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, &DialogStyling::OnListDoubleClicked, this);
	style_name->Bind(wxEVT_COMMAND_TEXT_UPDATED, &DialogStyling::OnStyleBoxModified, this);

	OnActiveLineChanged(c->selectionController->GetActiveLine());
}
// ---------------------------------------------------------------------
// mission_hotkey_do_frame()
//
// Called once per frame to process user input for the Hotkey Assignment Screen
//
void mission_hotkey_do_frame(float frametime)
{
	char buf[256];
	int i, k, w, h, y, z, line, hotkeys;
	int font_height = gr_get_font_height();
	int select_tease_line = -1;  // line mouse is down on, but won't be selected until button released
	color circle_color;

	if ( help_overlay_active(Hotkey_overlay_id) ) {
		Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
		Ui_window.set_ignore_gadgets(1);
	}

	k = Ui_window.process() & ~KEY_DEBUGGED;

	if ( (k > 0) || B1_JUST_RELEASED ) {
		if ( help_overlay_active(Hotkey_overlay_id) ) {
			help_overlay_set_state(Hotkey_overlay_id, gr_screen.res, 0);
			Ui_window.set_ignore_gadgets(0);
			k = 0;
		}
	}

	if ( !help_overlay_active(Hotkey_overlay_id) ) {
		Ui_window.set_ignore_gadgets(0);
	}

	switch (k) {
		case KEY_DOWN:  // scroll list down
			hotkey_scroll_line_down();
			break;

		case KEY_UP:  // scroll list up
			hotkey_scroll_line_up();
			break;

		case KEY_PAGEDOWN:  // scroll list down
			hotkey_scroll_screen_down();
			break;

		case KEY_PAGEUP:  // scroll list up
			hotkey_scroll_screen_up();
			break;

		case KEY_CTRLED | KEY_ENTER:
			save_hotkeys();
			// fall through to next state -- allender changed this behavior since ESC should always cancel, no?

		case KEY_ESC:			
			mission_hotkey_exit();
			break;

		case KEY_TAB:
		case KEY_ENTER:
		case KEY_PADENTER:
			expand_wing();
			break;

		case KEY_EQUAL:
		case KEY_PADPLUS:
			add_hotkey(Cur_hotkey);
			break;

		case KEY_MINUS:
		case KEY_PADMINUS:
			remove_hotkey();
			break;

		case KEY_F2:			
			gameseq_post_event(GS_EVENT_OPTIONS_MENU);			
			break;

		case KEY_CTRLED | KEY_R:
			reset_hotkeys();
			break;

		case KEY_CTRLED | KEY_C:
			clear_hotkeys();
			break;
	}	// end switch

	// ?
	for (i=0; i<MAX_KEYED_TARGETS; i++) {
		if (k == Key_sets[i])
			Cur_hotkey = i;

		if (k == (Key_sets[i] | KEY_SHIFTED))
			add_hotkey(i);
	}

	// handle pressed buttons
	for (i=0; i<NUM_BUTTONS; i++) {
		if (Buttons[gr_screen.res][i].button.pressed()) {
			hotkey_button_pressed(i);
			break;					// only need to handle 1 button @ a time
		}
	}

	for (i=0; i<LIST_BUTTONS_MAX; i++) {
		// check for tease line
		if (List_buttons[i].button_down()) {
			select_tease_line = i + Scroll_offset;
		}
	
		// check for selected list item
		if (List_buttons[i].pressed()) {
			Selected_line = i + Scroll_offset;
			List_buttons[i].get_mouse_pos(&z, NULL);
			z += Hotkey_list_coords[gr_screen.res][0];		// adjust to full screen space
			if ((z >= Hotkey_wing_icon_x[gr_screen.res]) && (z < (Hotkey_wing_icon_x[gr_screen.res]) + Hotkey_function_field_width[gr_screen.res])) {
				expand_wing();
			}
		}

		if (List_buttons[i].double_clicked()) {
			Selected_line = i + Scroll_offset;
			hotkeys = -1;
			switch (Hotkey_lines[Selected_line].type) {
				case HOTKEY_LINE_WING:
					hotkeys = get_wing_hotkeys(Hotkey_lines[Selected_line].index);
					break;

				case HOTKEY_LINE_SHIP:
				case HOTKEY_LINE_SUBSHIP:
					hotkeys = Hotkey_bits[Hotkey_lines[Selected_line].index];
					break;
			}

			if (hotkeys != -1) {
				if (hotkeys & (1 << Cur_hotkey))
					remove_hotkey();
				else
					add_hotkey(Cur_hotkey);
			}
		}
	}

	GR_MAYBE_CLEAR_RES(Background_bitmap);
	if (Background_bitmap >= 0) {
		gr_set_bitmap(Background_bitmap);
		gr_bitmap(0, 0, GR_RESIZE_MENU);

	} else
		gr_clear();

	Ui_window.draw();
	gr_init_color(&circle_color, 160, 160, 0);

	// draw the big "F10" in the little box	
	font::set_font(font::FONT2);
	gr_set_color_fast(&Color_text_normal);
	strcpy_s(buf, Scan_code_text[Key_sets[Cur_hotkey]]);
	gr_get_string_size(&w, &h, buf);
	gr_printf_menu(Hotkey_function_name_coords[gr_screen.res][0] + (Hotkey_function_name_coords[gr_screen.res][2] - w) / 2, Hotkey_function_name_coords[gr_screen.res][1], buf);

	font::set_font(font::FONT1);
	line = Scroll_offset;
	while (hotkey_line_query_visible(line)) {
		z = Hotkey_lines[line].index;
		y = Hotkey_list_coords[gr_screen.res][1] + Hotkey_lines[line].y - Hotkey_lines[Scroll_offset].y;
		hotkeys = 0;
		switch (Hotkey_lines[line].type) {
			case HOTKEY_LINE_HEADING:
				gr_set_color_fast(&Color_text_heading);

				gr_get_string_size(&w, &h, Hotkey_lines[line].label);
				i = y + h / 2 - 1;
				gr_line(Hotkey_list_coords[gr_screen.res][0], i, Hotkey_ship_x[gr_screen.res] - 2, i, GR_RESIZE_MENU);
				gr_line(Hotkey_ship_x[gr_screen.res] + w + 1, i, Hotkey_list_coords[gr_screen.res][0] + Hotkey_list_coords[gr_screen.res][2], i, GR_RESIZE_MENU);
				break;

			case HOTKEY_LINE_WING:
				gr_set_bitmap(Wing_bmp);
				bm_get_info(Wing_bmp, NULL, &h, NULL);
				i = y + font_height / 2 - h / 2 - 1;
				gr_bitmap(Hotkey_wing_icon_x[gr_screen.res], i, GR_RESIZE_MENU);

//				i = y + font_height / 2 - 1;
//				gr_set_color_fast(&circle_color);
//				gr_circle(ICON_LIST_X + 4, i, 5, GR_RESIZE_MENU);

//				gr_set_color_fast(&Color_bright);
//				gr_line(ICON_LIST_X, i, ICON_LIST_X + 2, i, GR_RESIZE_MENU);
//				gr_line(ICON_LIST_X + 4, i - 4, ICON_LIST_X + 4, i - 2, GR_RESIZE_MENU);
//				gr_line(ICON_LIST_X + 6, i, ICON_LIST_X + 8, i, GR_RESIZE_MENU);
//				gr_line(ICON_LIST_X + 4, i + 2, ICON_LIST_X + 4, i + 4, GR_RESIZE_MENU);

				hotkeys = get_wing_hotkeys(Hotkey_lines[line].index);
				break;

			case HOTKEY_LINE_SHIP:
			case HOTKEY_LINE_SUBSHIP:
				hotkeys = Hotkey_bits[Hotkey_lines[line].index];
				break;

			default:
				Int3();
		}

		if (Hotkey_lines[line].type != HOTKEY_LINE_HEADING) {
			Assert( (line - Scroll_offset) < LIST_BUTTONS_MAX );
			List_buttons[line - Scroll_offset].update_dimensions(Hotkey_list_coords[gr_screen.res][0], y, Hotkey_list_coords[gr_screen.res][0] + Hotkey_list_coords[gr_screen.res][2] - Hotkey_list_coords[gr_screen.res][0], font_height);
			List_buttons[line - Scroll_offset].enable();
			if (hotkeys & (1 << Cur_hotkey)) {
				gr_set_color_fast(&Color_text_active);

			} else {
				if (line == Selected_line)
					gr_set_color_fast(&Color_text_selected);
				else if (line == select_tease_line)
					gr_set_color_fast(&Color_text_subselected);
				else
					gr_set_color_fast(&Color_text_normal);
			}

		} else {
			Assert( (line - Scroll_offset) < LIST_BUTTONS_MAX );
			List_buttons[line - Scroll_offset].disable();
		}

		// print active hotkeys associated for this line
		if (hotkeys) {
			for (i=0; i<MAX_KEYED_TARGETS; i++) {
				if (hotkeys & (1 << i)) {
					gr_printf_menu(Hotkey_list_coords[gr_screen.res][0] + Hotkey_function_field_width[gr_screen.res]*i, y, Scan_code_text[Key_sets[i]]);
				}
			}
/*
			*buf = 0;
			for (i=0; i<MAX_KEYED_TARGETS; i++) {
				if (hotkeys & (1 << i)) {
					strcat_s(buf, Scan_code_text[Key_sets[i]]);
					strcat_s(buf, ", ");
				}
			}

			Assert(strlen(buf) > 1);
			buf[strlen(buf) - 2] = 0;  // lose the ", " on the end

			font::force_fit_string(buf, 255, GROUP_LIST_W);
			gr_printf_menu(GROUP_LIST_X, y, buf);*/
		}
	
		// draw ship/wing name
		strcpy_s(buf, Hotkey_lines[line].label);
		end_string_at_first_hash_symbol(buf);
		if (Hotkey_lines[line].type == HOTKEY_LINE_SUBSHIP) {
			// indent
			font::force_fit_string(buf, 255, Hotkey_list_coords[gr_screen.res][0] + Hotkey_list_coords[gr_screen.res][2] - (Hotkey_ship_x[gr_screen.res]+20));
			gr_printf_menu(Hotkey_ship_x[gr_screen.res]+20, y, buf);
		} else {
			font::force_fit_string(buf, 255, Hotkey_list_coords[gr_screen.res][0] + Hotkey_list_coords[gr_screen.res][2] - Hotkey_ship_x[gr_screen.res]);
			gr_printf_menu(Hotkey_ship_x[gr_screen.res], y, buf);
		}

		line++;
	}

	i = line - Scroll_offset;
	while (i < LIST_BUTTONS_MAX)
		List_buttons[i++].disable();

	// blit help overlay if active
	help_overlay_maybe_blit(Hotkey_overlay_id, gr_screen.res);

	gr_flip();
}
예제 #8
0
DialogTranslation::DialogTranslation(agi::Context *c)
: wxDialog(c->parent, -1, _("Translation Assistant"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX)
, c(c)
, file_change_connection(c->ass->AddCommitListener(&DialogTranslation::OnExternalCommit, this))
, active_line_connection(c->selectionController->AddActiveLineListener(&DialogTranslation::OnActiveLineChanged, this))
, active_line(c->selectionController->GetActiveLine())
, line_count(count_if(c->ass->Line.begin(), c->ass->Line.end(), cast<AssDialogue*>()))
, line_number(count_if(c->ass->Line.begin(), c->ass->Line.iterator_to(*active_line), cast<AssDialogue*>()) + 1)
{
	SetIcon(GETICON(translation_toolbutton_16));

	wxSizer *main_sizer = new wxBoxSizer(wxVERTICAL);

	wxSizer *translation_sizer = new wxBoxSizer(wxVERTICAL);
	{
		wxSizer *original_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Original"));

		line_number_display = new wxStaticText(this, -1, "");
		original_box->Add(line_number_display, 0, wxBOTTOM, 5);

		original_text = new ScintillaTextCtrl(this, -1, "", wxDefaultPosition, wxSize(320, 80));
		original_text->SetWrapMode(wxSTC_WRAP_WORD);
		original_text->SetMarginWidth(1, 0);
		original_text->StyleSetForeground(1, wxColour(10, 60, 200));
		original_text->SetReadOnly(true);
		original_box->Add(original_text, 1, wxEXPAND, 0);

		translation_sizer->Add(original_box, 1, wxEXPAND, 0);
	}

	{
		translated_text = new SubsTextEditCtrl(this, wxSize(320, 80), 0, nullptr);
		translated_text->SetWrapMode(wxSTC_WRAP_WORD);
		translated_text->SetMarginWidth(1, 0);
		translated_text->SetFocus();
		translated_text->Bind(wxEVT_CHAR_HOOK, &DialogTranslation::OnKeyDown, this);

		wxSizer *translated_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Translation"));
		translated_box->Add(translated_text, 1, wxEXPAND, 0);
		translation_sizer->Add(translated_box, 1, wxTOP|wxEXPAND, 5);
	}
	main_sizer->Add(translation_sizer, 1, wxALL | wxEXPAND, 5);

	wxSizer *right_box = new wxBoxSizer(wxHORIZONTAL);
	{
		wxSizer *hotkey_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Keys"));

		wxSizer *hotkey_grid = new wxGridSizer(2, 0, 5);
		add_hotkey(hotkey_grid, this, "tool/translation_assistant/commit", _("Accept changes"));
		add_hotkey(hotkey_grid, this, "tool/translation_assistant/preview", _("Preview changes"));
		add_hotkey(hotkey_grid, this, "tool/translation_assistant/prev", _("Previous line"));
		add_hotkey(hotkey_grid, this, "tool/translation_assistant/next", _("Next line"));
		add_hotkey(hotkey_grid, this, "tool/translation_assistant/insert_original", _("Insert original"));
		add_hotkey(hotkey_grid, this, "video/play/line", _("Play video"));
		add_hotkey(hotkey_grid, this, "audio/play/selection", _("Play audio"));
		add_hotkey(hotkey_grid, this, "edit/line/delete", _("Delete line"));
		hotkey_box->Add(hotkey_grid, 0, wxEXPAND, 0);

		seek_video = new wxCheckBox(this, -1, _("Enable &preview"));
		seek_video->SetValue(true);
		hotkey_box->Add(seek_video, 0, wxTOP, 5);

		right_box->Add(hotkey_box, 1, wxRIGHT | wxEXPAND, 5);
	}

	{
		wxStaticBoxSizer *actions_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Actions"));

		wxButton *play_audio = new wxButton(this, -1, _("Play &Audio"));
		play_audio->Enable(c->audioController->IsAudioOpen());
		play_audio->Bind(wxEVT_BUTTON, &DialogTranslation::OnPlayAudioButton, this);
		actions_box->Add(play_audio, 0, wxALL, 5);

		wxButton *play_video = new wxButton(this, -1, _("Play &Video"));
		play_video->Enable(c->videoController->IsLoaded());
		play_video->Bind(wxEVT_BUTTON, &DialogTranslation::OnPlayVideoButton, this);
		actions_box->Add(play_video, 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);

		right_box->Add(actions_box, 0);
	}
	main_sizer->Add(right_box, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);

	{
		auto standard_buttons = new wxStdDialogButtonSizer();
		standard_buttons->AddButton(new wxButton(this, wxID_CANCEL));
		standard_buttons->AddButton(new HelpButton(this, "Translation Assistant"));
		standard_buttons->Realize();
		main_sizer->Add(standard_buttons, 0, wxALIGN_RIGHT | wxLEFT | wxBOTTOM | wxRIGHT, 5);
	}

	SetSizerAndFit(main_sizer);

	persist = agi::util::make_unique<PersistLocation>(this, "Tool/Translation Assistant");

	Bind(wxEVT_KEY_DOWN, &DialogTranslation::OnKeyDown, this);

	blocks = active_line->ParseTags();
	if (bad_block(blocks[0])) {
		if (!NextBlock())
			throw NothingToTranslate(from_wx(_("There is nothing to translate in the file.")));
	}
	else
		UpdateDisplay();
}