Commit 7e28a47b authored by Jim Nelson's avatar Jim Nelson

#138: Actions and ActionGroups now handled in intelligent manner. Also added...

#138: Actions and ActionGroups now handled in intelligent manner.  Also added moveable thumb between sidebar and 
view pages.
parent 71a75541
......@@ -4,11 +4,14 @@ public class AppWindow : Gtk.Window {
public static const string VERSION = "0.0.1";
public static const string DATA_DIR = ".photo";
public static const string PHOTOS_DIR = "Pictures";
public static const int SIDEBAR_MIN_WIDTH = 160;
public static const int SIDEBAR_MAX_WIDTH = 320;
public static const int PAGE_MIN_WIDTH =
Thumbnail.MAX_SCALE + CollectionLayout.LEFT_PADDING + CollectionLayout.RIGHT_PADDING;
public static Gdk.Color BG_COLOR = parse_color("#777");
private static AppWindow mainWindow = null;
private static Gtk.UIManager uiManager = null;
private static string[] args = null;
// drag and drop target entries
......@@ -16,6 +19,13 @@ public class AppWindow : Gtk.Window {
{ "text/uri-list", 0, 0 }
};
// Common actions available to all pages
// TODO: Mark fields for translation
private const Gtk.ActionEntry[] COMMON_ACTIONS = {
{ "CommonQuit", Gtk.STOCK_QUIT, "_Quit", "<Ctrl>Q", "Quit Shotwell", Gtk.main_quit },
{ "CommonAbout", Gtk.STOCK_ABOUT, "_About", null, "About Shotwell", on_about }
};
public static void init(string[] args) {
AppWindow.args = args;
......@@ -29,27 +39,12 @@ public class AppWindow : Gtk.Window {
} catch (Error err) {
error("%s", err.message);
}
uiManager = new Gtk.UIManager();
File uiFile = get_exec_dir().get_child("photo.ui");
assert(uiFile != null);
try {
uiManager.add_ui_from_file(uiFile.get_path());
} catch (GLib.Error gle) {
error("Error loading UI: %s", gle.message);
}
}
public static AppWindow get_main_window() {
return mainWindow;
}
public static Gtk.UIManager get_ui_manager() {
return uiManager;
}
public static string[] get_commandline_args() {
return args;
}
......@@ -88,12 +83,7 @@ public class AppWindow : Gtk.Window {
return subdir;
}
private Gtk.TreeStore pageTreeStore = null;
private Gtk.TreeView pageTreeView = null;
private Gtk.TreePath collectionPath = null;
private Gtk.TreePath importPath = null;
private CollectionPage collectionPage = null;
private PhotoPage photoPage = null;
private ImportPage importPage = null;
......@@ -102,87 +92,48 @@ public class AppWindow : Gtk.Window {
private PhotoTable photoTable = new PhotoTable();
construct {
// set up display
// if this is the first AppWindow, it's the main AppWindow
if (mainWindow == null) {
mainWindow = this;
}
title = TITLE;
set_default_size(1024, 768);
destroy += Gtk.main_quit;
pageTreeStore = new Gtk.TreeStore(1, typeof(string));
pageTreeView = new Gtk.TreeView.with_model(pageTreeStore);
var text = new Gtk.CellRendererText();
text.size_points = 9.0;
var column = new Gtk.TreeViewColumn();
column.pack_start(text, true);
column.add_attribute(text, "text", 0);
pageTreeView.append_column(column);
pageTreeView.set_headers_visible(false);
Gtk.TreeIter parent, child;
pageTreeStore.append(out parent, null);
pageTreeStore.set(parent, 0, "Photos");
collectionPath = pageTreeStore.get_path(parent);
pageTreeView.get_selection().select_path(collectionPath);
pageTreeStore.append(out parent, null);
pageTreeStore.set(parent, 0, "Events");
pageTreeStore.append(out child, parent);
pageTreeStore.set(child, 0, "New Year's");
pageTreeStore.append(out parent, null);
pageTreeStore.set(parent, 0, "Albums");
pageTreeStore.append(out child, parent);
pageTreeStore.set(child, 0, "Parties");
pageTreeStore.append(out parent, null);
pageTreeStore.set(parent, 0, null);
pageTreeStore.append(out parent, null);
pageTreeStore.set(parent, 0, "Import");
importPath = pageTreeStore.get_path(parent);
pageTreeStore.append(out parent, null);
pageTreeStore.set(parent, 0, "Recent");
pageTreeStore.append(out parent, null);
pageTreeStore.set(parent, 0, "Trash");
pageTreeView.cursor_changed += () => {
Gtk.TreePath selected;
pageTreeView.get_cursor(out selected, null);
if (selected.compare(collectionPath) == 0) {
switch_to_collection_page();
} else if (selected.compare(importPath) == 0) {
switch_to_import_page();
} else {
debug("unknown");
}
};
// set up as a drag-and-drop destination
// this.drag_data_received() is called when a drop occurs
Gtk.drag_dest_set(this, Gtk.DestDefaults.ALL, TARGET_ENTRIES, Gdk.DragAction.COPY);
// if this is the first AppWindow, it's the main AppWindow
if (mainWindow == null) {
mainWindow = this;
}
build_sidebar();
collectionPage = new CollectionPage();
photoPage = new PhotoPage("Photo");
photoPage = new PhotoPage();
importPage = new ImportPage();
importPreviewPage = new PhotoPage("ImportPreview");
importPreviewPage = new PhotoPage();
add_accel_group(uiManager.get_accel_group());
create_start_page();
// set up main window as a drag-and-drop destination (rather than each page; assume
// a drag and drop is for general library importation, which means it goes to collectionPage)
Gtk.drag_dest_set(this, Gtk.DestDefaults.ALL, TARGET_ENTRIES, Gdk.DragAction.COPY);
}
public Gtk.ActionGroup get_common_action_group() {
// each page gets its own one
Gtk.ActionGroup actionGroup = new Gtk.ActionGroup("CommonActionGroup");
actionGroup.add_actions(COMMON_ACTIONS, this);
return actionGroup;
}
public void on_about() {
// TODO: More thorough About box
Gtk.show_about_dialog(this,
"version", AppWindow.VERSION,
"comments", "A photo organizer",
"copyright", "(c) 2009 Yorba Foundation",
"website", "http://www.yorba.org"
);
}
public void import(File file) {
FileType type = file.query_file_type(FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
if(type == FileType.REGULAR) {
......@@ -303,32 +254,48 @@ public class AppWindow : Gtk.Window {
private Gtk.Box layout = null;
private Gtk.Box pageBox = null;
private Gtk.Box clientBox = null;
private Gtk.Paned clientPaned = null;
private Page currentPage = null;
private Gtk.MenuBar currentMenuBar = null;
private void create_start_page() {
currentPage = collectionPage;
// layout the growable collection page with the toolbar beneath
pageBox = new Gtk.VBox(false, 0);
pageBox.pack_start(collectionPage, true, true, 0);
pageBox.pack_start(currentPage, true, true, 0);
pageBox.pack_end(currentPage.get_toolbar(), false, false, 0);
// layout the selection tree to the left of the collection/toolbar box
clientBox = new Gtk.HBox(false, 0);
clientBox.pack_start(pageTreeView, false, false, 0);
clientBox.pack_end(pageBox, true, true, 0);
// put the sidebar in a scrolling window
Gtk.ScrolledWindow scrolledSidebar = new Gtk.ScrolledWindow(null, null);
scrolledSidebar.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
scrolledSidebar.add(sidebar);
// layout the selection tree to the left of the collection/toolbar box with an adjustable
// gutter between them, framed for presentation
Gtk.Frame leftFrame = new Gtk.Frame(null);
leftFrame.add(scrolledSidebar);
leftFrame.set_shadow_type(Gtk.ShadowType.IN);
currentMenuBar = (Gtk.MenuBar) get_ui_manager().get_widget(currentPage.get_menubar_path());
Gtk.Frame rightFrame = new Gtk.Frame(null);
rightFrame.add(pageBox);
rightFrame.set_shadow_type(Gtk.ShadowType.IN);
clientPaned = new Gtk.HPaned();
clientPaned.pack1(leftFrame, false, false);
sidebar.set_size_request(SIDEBAR_MIN_WIDTH, -1);
clientPaned.pack2(rightFrame, true, false);
// TODO: Calc according to layout's size, to give sidebar a maximum width
pageBox.set_size_request(PAGE_MIN_WIDTH, -1);
// layout client beneath menu
layout = new Gtk.VBox(false, 0);
layout.pack_start(currentMenuBar, false, false, 0);
layout.pack_end(clientBox, true, true, 0);
layout.pack_start(currentPage.get_menubar(), false, false, 0);
layout.pack_end(clientPaned, true, true, 0);
add(layout);
add_accel_group(currentPage.ui.get_accel_group());
currentPage.switched_to();
show_all();
......@@ -339,6 +306,8 @@ public class AppWindow : Gtk.Window {
return;
currentPage.switching_from();
remove_accel_group(currentPage.ui.get_accel_group());
pageBox.remove(currentPage);
pageBox.pack_start(page, true, true, 0);
......@@ -346,9 +315,10 @@ public class AppWindow : Gtk.Window {
pageBox.remove(currentPage.get_toolbar());
pageBox.pack_end(page.get_toolbar(), false, false, 0);
layout.remove(currentMenuBar);
currentMenuBar = (Gtk.MenuBar) get_ui_manager().get_widget(page.get_menubar_path());
layout.pack_start(currentMenuBar, false, false, 0);
layout.remove(currentPage.get_menubar());
layout.pack_start(page.get_menubar(), false, false, 0);
add_accel_group(page.ui.get_accel_group());
page.switched_to();
......@@ -356,5 +326,71 @@ public class AppWindow : Gtk.Window {
currentPage = page;
}
private Gtk.TreeView sidebar = null;
private Gtk.TreeStore sidebarStore = null;
private Gtk.TreePath collectionPath = null;
private Gtk.TreePath importPath = null;
private void build_sidebar() {
sidebarStore = new Gtk.TreeStore(1, typeof(string));
sidebar = new Gtk.TreeView.with_model(sidebarStore);
var text = new Gtk.CellRendererText();
text.size_points = 9.0;
var column = new Gtk.TreeViewColumn();
column.pack_start(text, true);
column.add_attribute(text, "text", 0);
sidebar.append_column(column);
sidebar.set_headers_visible(false);
Gtk.TreeIter parent, child;
sidebarStore.append(out parent, null);
sidebarStore.set(parent, 0, "Photos");
collectionPath = sidebarStore.get_path(parent);
// start in the collection page
sidebar.get_selection().select_path(collectionPath);
sidebarStore.append(out parent, null);
sidebarStore.set(parent, 0, "Events");
sidebarStore.append(out child, parent);
sidebarStore.set(child, 0, "New Year's");
sidebarStore.append(out parent, null);
sidebarStore.set(parent, 0, "Albums");
sidebarStore.append(out child, parent);
sidebarStore.set(child, 0, "Parties");
sidebarStore.append(out parent, null);
sidebarStore.set(parent, 0, null);
sidebarStore.append(out parent, null);
sidebarStore.set(parent, 0, "Import");
importPath = sidebarStore.get_path(parent);
sidebarStore.append(out parent, null);
sidebarStore.set(parent, 0, "Recent");
sidebarStore.append(out parent, null);
sidebarStore.set(parent, 0, "Trash");
sidebar.cursor_changed += on_sidebar_cursor_changed;
}
private void on_sidebar_cursor_changed() {
Gtk.TreePath selected;
sidebar.get_cursor(out selected, null);
if (selected.compare(collectionPath) == 0) {
switch_to_collection_page();
} else if (selected.compare(importPath) == 0) {
switch_to_import_page();
} else {
debug("unknown");
}
}
}
......@@ -11,8 +11,6 @@ public class CollectionPage : CheckerboardPage {
private static const int IMPROVAL_DELAY_MS = 250;
private PhotoTable photoTable = new PhotoTable();
private Gtk.ActionGroup mainActionGroup = new Gtk.ActionGroup("CollectionActionGroup");
private Gtk.ActionGroup contextActionGroup = new Gtk.ActionGroup("CollectionContextActionGroup");
private Gtk.Toolbar toolbar = new Gtk.Toolbar();
private Gtk.HScale slider = null;
private Gtk.ToolButton rotateButton = null;
......@@ -22,39 +20,38 @@ public class CollectionPage : CheckerboardPage {
// TODO: Mark fields for translation
private const Gtk.ActionEntry[] ACTIONS = {
{ "File", null, "_File", null, null, null },
{ "Quit", Gtk.STOCK_QUIT, "_Quit", null, "Quit the program", Gtk.main_quit },
{ "Edit", null, "_Edit", null, null, on_edit_menu },
{ "FileMenu", null, "_File", null, null, null },
{ "EditMenu", null, "_Edit", null, null, on_edit_menu },
{ "SelectAll", Gtk.STOCK_SELECT_ALL, "Select _All", "<Ctrl>A", "Select all the photos in the library", on_select_all },
{ "Remove", Gtk.STOCK_DELETE, "_Remove", "Delete", "Remove the selected photos from the library", on_remove },
{ "Photos", null, "_Photos", null, null, on_photos_menu },
{ "PhotosMenu", null, "_Photos", null, null, on_photos_menu },
{ "IncreaseSize", Gtk.STOCK_ZOOM_IN, "Zoom _in", "KP_Add", "Increase the magnification of the thumbnails", on_increase_size },
{ "DecreaseSize", Gtk.STOCK_ZOOM_OUT, "Zoom _out", "KP_Subtract", "Decrease the magnification of the thumbnails", on_decrease_size },
{ "RotateClockwise", STOCK_CLOCKWISE, "Rotate c_lockwise", "<Ctrl>R", "Rotate the selected photos clockwise", on_rotate_clockwise },
{ "RotateCounterclockwise", STOCK_COUNTERCLOCKWISE, "Rotate c_ounterclockwise", "<Ctrl><Shift>R", "Rotate the selected photos counterclockwise", on_rotate_counterclockwise },
{ "Mirror", null, "_Mirror", "<Ctrl>M", "Make mirror images of the selected photos", on_mirror },
{ "View", null, "_View", null, null, null },
{ "ViewMenu", null, "_View", null, null, null },
{ "ViewTitle", null, "_Titles", "<Ctrl><Shift>T", "Display the title of each photo", on_display_titles },
{ "Help", null, "_Help", null, null, null },
{ "About", Gtk.STOCK_ABOUT, "_About", null, "About this application", about_box }
{ "HelpMenu", null, "_Help", null, null, null }
};
// TODO: Mark fields for translation
/*
private const Gtk.ActionEntry[] RIGHT_CLICK_ACTIONS = {
{ "Remove", Gtk.STOCK_DELETE, "_Remove", "Delete", "Remove the selected photos from the library", on_remove },
{ "CollectionRotateClockwise", STOCK_CLOCKWISE, "Rotate c_lockwise", "<Ctrl>R", "Rotate the selected photos clockwise", on_rotate_clockwise },
{ "CollectionRotateCounterclockwise", STOCK_COUNTERCLOCKWISE, "Rotate c_ounterclockwise", "<Ctrl><Shift>R", "Rotate the selected photos counterclockwise", on_rotate_counterclockwise },
{ "CollectionMirror", null, "_Mirror", "<Ctrl>M", "Make mirror images of the selected photos", on_mirror }
};
*/
construct {
// set up action group
mainActionGroup.add_actions(ACTIONS, this);
AppWindow.get_ui_manager().insert_action_group(mainActionGroup, 0);
contextActionGroup.add_actions(RIGHT_CLICK_ACTIONS, this);
AppWindow.get_ui_manager().insert_action_group(contextActionGroup, 0);
init_ui("collection.ui", "/CollectionMenuBar", "CollectionActionGroup", ACTIONS);
init_context_menu("/CollectionContextMenu");
// set up page's toolbar (used by AppWindow for layout)
//
......@@ -110,14 +107,6 @@ public class CollectionPage : CheckerboardPage {
return toolbar;
}
public override string get_menubar_path() {
return "/CollectionMenuBar";
}
public override string? get_context_menu_path() {
return "/CollectionContextMenu";
}
public override void switched_to() {
// need to refresh the layout in case any of the thumbnail dimensions were altered while we
// were gone
......@@ -241,8 +230,8 @@ public class CollectionPage : CheckerboardPage {
}
private void on_edit_menu() {
set_item_sensitive("/CollectionMenuBar/EditMenu/EditSelectAll", get_count() > 0);
set_item_sensitive("/CollectionMenuBar/EditMenu/EditRemove", get_selected_count() > 0);
set_item_sensitive("/CollectionMenuBar/EditMenu/SelectAll", get_count() > 0);
set_item_sensitive("/CollectionMenuBar/EditMenu/Remove", get_selected_count() > 0);
}
private void on_select_all() {
......@@ -252,8 +241,8 @@ public class CollectionPage : CheckerboardPage {
private void on_photos_menu() {
bool selected = (get_selected_count() > 0);
set_item_sensitive("/CollectionMenuBar/PhotosMenu/PhotosIncreaseSize", scale < Thumbnail.MAX_SCALE);
set_item_sensitive("/CollectionMenuBar/PhotosMenu/PhotosDecreaseSize", scale > Thumbnail.MIN_SCALE);
set_item_sensitive("/CollectionMenuBar/PhotosMenu/IncreaseSize", scale < Thumbnail.MAX_SCALE);
set_item_sensitive("/CollectionMenuBar/PhotosMenu/DecreaseSize", scale > Thumbnail.MIN_SCALE);
set_item_sensitive("/CollectionMenuBar/PhotosMenu/RotateClockwise", selected);
set_item_sensitive("/CollectionMenuBar/PhotosMenu/RotateCounterclockwise", selected);
set_item_sensitive("/CollectionMenuBar/PhotosMenu/Mirror", selected);
......
......@@ -28,7 +28,6 @@ public class ImportPreview : LayoutItem {
}
public class ImportPage : CheckerboardPage {
private Gtk.ActionGroup actionGroup = new Gtk.ActionGroup("ImportActionGroup");
private Gtk.Toolbar toolbar = new Gtk.Toolbar();
private Gtk.Label cameraLabel = new Gtk.Label(null);
private Gtk.ToolButton refreshButton = new Gtk.ToolButton.from_stock(Gtk.STOCK_REFRESH);
......@@ -42,19 +41,16 @@ public class ImportPage : CheckerboardPage {
// TODO: Mark fields for translation
private const Gtk.ActionEntry[] ACTIONS = {
{ "File", null, "_File", null, null, on_file },
{ "FileMenu", null, "_File", null, null, on_file },
{ "ImportSelected", null, "Import _Selected", null, null, on_import_selected },
{ "ImportAll", null, "Import _All", null, null, on_import_all },
{ "Quit", Gtk.STOCK_QUIT, "_Quit", null, "Quit the program", Gtk.main_quit },
{ "Help", null, "_Help", null, null, null },
{ "About", Gtk.STOCK_ABOUT, "_About", null, "About this application", about_box }
{ "HelpMenu", null, "_Help", null, null, null }
};
construct {
actionGroup.add_actions(ACTIONS, this);
AppWindow.get_ui_manager().insert_action_group(actionGroup, 0);
init_ui("import.ui", "/ImportMenuBar", "ImportActionGroup", ACTIONS);
// toolbar
// Refresh button
refreshButton.sensitive = false;
......@@ -118,10 +114,6 @@ public class ImportPage : CheckerboardPage {
}
}
public override string get_menubar_path() {
return "/ImportMenuBar";
}
public override Gtk.Toolbar get_toolbar() {
return toolbar;
}
......@@ -244,6 +236,7 @@ public class ImportPage : CheckerboardPage {
}
remove_all();
refreshButton.sensitive = false;
importSelectedButton.sensitive = false;
importAllButton.sensitive = false;
......@@ -259,6 +252,7 @@ public class ImportPage : CheckerboardPage {
previewCount += load_preview(basedir);
}
refreshButton.sensitive = true;
importAllButton.sensitive = (previewCount > 0);
res = camera.exit(context);
......@@ -306,6 +300,11 @@ public class ImportPage : CheckerboardPage {
count++;
refresh();
// spin the event loop so the UI doesn't freeze
// TODO: Background thread
while (Gtk.events_pending())
Gtk.main_iteration();
} catch (Error err) {
error("%s", err.message);
}
......
......@@ -2,7 +2,7 @@
TARGET = shotwell
# This takes care of a warning message generated by the use of Math.round in image_util.vala
VALAC_OPTS =--Xcc=-std=c99
VALAC_OPTS =--Xcc=-std=c99 -g --enable-checking
SRC_FILES = \
main.vala \
......@@ -25,7 +25,9 @@ VAPI_FILES = \
libgphoto2.vapi
RESOURCE_FILES = \
photo.ui
photo.ui \
collection.ui \
import.ui
VAPI_DIRS = \
.
......
......@@ -40,6 +40,10 @@ public abstract class Page : Gtk.ScrolledWindow {
factory.add_default();
}
public Gtk.UIManager ui = new Gtk.UIManager();
public Gtk.ActionGroup actionGroup = null;
public Gtk.MenuBar menuBar = null;
construct {
prepIcons();
......@@ -49,7 +53,9 @@ public abstract class Page : Gtk.ScrolledWindow {
AppWindow.get_main_window().configure_event += on_configure;
}
public abstract string get_menubar_path();
public virtual Gtk.MenuBar get_menubar() {
return menuBar;
}
public abstract Gtk.Toolbar get_toolbar();
......@@ -59,19 +65,8 @@ public abstract class Page : Gtk.ScrolledWindow {
public virtual void switched_to() {
}
public void about_box() {
// TODO: More thorough About box
Gtk.show_about_dialog(AppWindow.get_main_window(),
"version", AppWindow.VERSION,
"comments", "a photo organizer",
"copyright", "(c) 2009 yorba",
"website", "http://www.yorba.org"
);
}
public void set_item_sensitive(string path, bool sensitive) {
Gtk.Widget widget = AppWindow.get_ui_manager().get_widget(path);
widget.set_sensitive(sensitive);
ui.get_widget(path).sensitive = sensitive;
}
protected virtual bool on_left_click(Gdk.EventButton event) {
......@@ -86,6 +81,28 @@ public abstract class Page : Gtk.ScrolledWindow {
return false;
}
protected void init_ui(string uiFilename, string menuBarPath, string actionGroupName,
Gtk.ActionEntry[] entries) {
File uiFile = AppWindow.get_exec_dir().get_child(uiFilename);
try {
ui.add_ui_from_file(uiFile.get_path());
} catch (Error gle) {
error("Error loading UI file %s: %s", uiFilename, gle.message);
}
actionGroup = new Gtk.ActionGroup(actionGroupName);
actionGroup.add_actions(entries, this);
ui.insert_action_group(actionGroup, 0);
ui.insert_action_group(AppWindow.get_main_window().get_common_action_group(), 0);
if (menuBarPath != null)
menuBar = (Gtk.MenuBar) ui.get_widget(menuBarPath);
ui.ensure_update();
}
private bool on_click(Page p, Gdk.EventButton event) {
switch (event.button) {
case 1:
......@@ -166,6 +183,7 @@ public abstract class Page : Gtk.ScrolledWindow {
}
public abstract class CheckerboardPage : Page {
private Gtk.Menu contextMenu = null;
private CollectionLayout layout = new CollectionLayout();
private Gee.ArrayList<LayoutItem> items = new Gee.ArrayList<LayoutItem>();
private Gee.HashSet<LayoutItem> selectedItems = new Gee.HashSet<LayoutItem>();
......@@ -174,11 +192,15 @@ public abstract class CheckerboardPage : Page {
add(layout);
}
protected void init_context_menu(string path) {
contextMenu = (Gtk.Menu) ui.get_widget(path);
}
protected virtual void on_selection_changed(int count) {
}
public virtual string? get_context_menu_path() {
return null;
public virtual Gtk.Menu get_context_menu(LayoutItem item) {
return contextMenu;
}
public virtual void on_item_activated(LayoutItem item) {
......@@ -344,16 +366,15 @@ public abstract class CheckerboardPage : Page {
LayoutItem item = get_item_at(event.x, event.y);
if (item != null) {
// this counts as a select with all others de-selected
// TODO: Enable context menus for multiple and single selections
unselect_all();
select(item);
}
string contextPath = get_context_menu_path();
if (contextPath != null) {
Gtk.Menu contextMenu = (Gtk.Menu) AppWindow.get_ui_manager().get_widget(contextPath);
contextMenu.popup(null, null, null, event.button, event.time);
}
Gtk.Menu contextMenu = get_context_menu(item);
if (contextMenu != null) {
contextMenu.popup(null, null, null, event.button, event.time);
return true;
}
......
......@@ -5,7 +5,6 @@ public class PhotoPage : Page {
private PhotoTable photoTable = new PhotoTable();
private Gtk.Viewport viewport = new Gtk.Viewport(null, null);
private Gtk.ActionGroup actionGroup = null;
private Gtk.Toolbar toolbar = new Gtk.Toolbar();
private Gtk.ToolButton rotateButton = null;
private Gtk.Image image = new Gtk.Image();
......@@ -19,29 +18,26 @@ public class PhotoPage : Page {
// TODO: Mark fields for translation
private const Gtk.ActionEntry[] ACTIONS = {
{ "File", null, "_File", null, null, null },
{ "Quit", Gtk.STOCK_QUIT, "_Quit", null, "Quit the program", Gtk.main_quit },
{ "PhotoAction", null, "_Photo", null, null, null },
{ "PhotoRotateClockwise", STOCK_CLOCKWISE, "Rotate c_lockwise", "<Ctrl>R", "Rotate the selected photos clockwise", on_rotate_clockwise },
{ "PhotoRotateCounterclockwise", STOCK_COUNTERCLOCKWISE, "Rotate c_ounterclockwise", "<Ctrl><Shift>R", "Rotate the selected photos counterclockwise", on_rotate_counterclockwise },
{ "PhotoMirror", null, "_Mirror", "<Ctrl>M", "Make mirror images of the selected photos", on_mirror },
{ "Help", null, "_Help", null, null, null },
{ "About", Gtk.STOCK_ABOUT, "_About", null, "About this application", about_box }
{ "FileMenu", null, "_File", null, null, null },
{ "PhotoMenu", null, "_Photo", null, null, null },
{ "RotateClockwise", STOCK_CLOCKWISE, "Rotate c_lockwise", "<Ctrl>R", "Rotate the selected photos clockwise", on_rotate_clockwise },
{ "RotateCounterclockwise", STOCK_COUNTERCLOCKWISE, "Rotate c_ounterclockwise", "<Ctrl><Shift>R", "Rotate the selected photos counterclockwise", on_rotate_counterclockwise },
{ "Mirror", null, "_Mirror", "<Ctrl>M", "Make mirror images of the selected photos", on_mirror },
{ "HelpMenu", null, "_Help", null, null, null }
};
construct {
init_ui("photo.ui", "/PhotoMenuBar", "PhotoActionGroup", ACTIONS);
// set up page's toolbar (used by AppWindow for layout)
//
// rotate tool
rotateButton = new Gtk.ToolButton.from_stock(STOCK_CLOCKWISE);
rotateButton.clicked += on_rotate_clockwise;
toolbar.insert(rotateButton, -1);