Commit 72186fb1 authored by Jim Nelson's avatar Jim Nelson

#55: Slider control added. Also, refactored code so CollectionPage

provides menu bar and tool bar.  Eventually AppWindow will become a 
controller merely switching between various pages (views).
parent b2636cea
......@@ -8,23 +8,6 @@ public class AppWindow : Gtk.Window {
private static Gtk.UIManager uiManager = null;
private static string[] args = null;
// 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 },
{ "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, null },
{ "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 },
{ "Help", null, "_Help", null, null, null },
{ "About", Gtk.STOCK_ABOUT, "_About", null, "About this application", on_about }
};
// drag and drop target entries
private const Gtk.TargetEntry[] TARGET_ENTRIES = {
{ "text/uri-list", 0, 0 }
......@@ -109,16 +92,6 @@ public class AppWindow : Gtk.Window {
destroy += Gtk.main_quit;
// window actions
Gtk.ActionGroup actionGroup = new Gtk.ActionGroup("MainActionGroup");
actionGroup.add_actions(ACTIONS, this);
uiManager.insert_action_group(actionGroup, 0);
// primary widgets
Gtk.MenuBar menubar = (Gtk.MenuBar) uiManager.get_widget("/MenuBar");
add_accel_group(uiManager.get_accel_group());
Gtk.TreeStore pageTreeStore = new Gtk.TreeStore(1, typeof(string));
Gtk.TreeView pageTreeView = new Gtk.TreeView.with_model(pageTreeStore);
pageTreeView.modify_bg(Gtk.StateType.NORMAL, parse_color(CollectionPage.BG_COLOR));
......@@ -159,7 +132,7 @@ public class AppWindow : Gtk.Window {
pageTreeStore.append(out parent, null);
pageTreeStore.set(parent, 0, "Trash");
// 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);
......@@ -172,20 +145,25 @@ public class AppWindow : Gtk.Window {
photoTable = new PhotoTable();
collectionPage = new CollectionPage();
// layout the selection tree and the view side-by-side
Gtk.HBox hbox = new Gtk.HBox(false, 0);
hbox.pack_start(pageTreeView, false, false, 0);
hbox.pack_end(collectionPage, true, true, 0);
// layout the growable collection page with the toolbar beneath
Gtk.VBox pageBox = new Gtk.VBox(false, 0);
pageBox.pack_start(collectionPage, true, true, 0);
pageBox.pack_end(collectionPage.get_toolbar(), false, false, 0);
// layout the selection tree to the left of the collection/toolbar box
Gtk.HBox clientBox = new Gtk.HBox(false, 0);
clientBox.pack_start(pageTreeView, false, false, 0);
clientBox.pack_end(pageBox, true, true, 0);
// layout everything vertically inside the main window
Gtk.VBox vbox = new Gtk.VBox(false, 0);
vbox.pack_start(menubar, false, false, 0);
vbox.pack_end(hbox, true, true, 0);
// layout client beneath menu
Gtk.VBox mainBox = new Gtk.VBox(false, 0);
mainBox.pack_start(collectionPage.get_menubar(), false, false, 0);
mainBox.pack_end(clientBox, true, true, 0);
add(vbox);
add(mainBox);
}
private void on_about() {
public void about_box() {
// TODO: More thorough About box
Gtk.show_about_dialog(this,
"version", VERSION,
......@@ -276,38 +254,5 @@ public class AppWindow : Gtk.Window {
import(File.new_for_uri(uri));
}
}
private void set_item_sensitive(string path, bool sensitive) {
Gtk.Widget widget = uiManager.get_widget(path);
widget.set_sensitive(sensitive);
}
private void on_edit_menu() {
set_item_sensitive("/MenuBar/EditMenu/EditSelectAll", collectionPage.get_count() > 0);
set_item_sensitive("/MenuBar/EditMenu/EditRemove", collectionPage.get_selected_count() > 0);
}
private void on_remove() {
Thumbnail[] thumbnails = collectionPage.get_selected();
foreach (Thumbnail thumbnail in thumbnails) {
collectionPage.remove_photo(thumbnail);
ThumbnailCache.big.remove(photoTable.get_id(thumbnail.get_file()));
photoTable.remove(thumbnail.get_file());
}
collectionPage.repack();
}
private void on_select_all() {
collectionPage.select_all();
}
private void on_increase_size() {
collectionPage.increase_thumb_size();
}
private void on_decrease_size() {
collectionPage.decrease_thumb_size();
}
}
......@@ -4,9 +4,12 @@ public class CollectionPage : Gtk.ScrolledWindow {
public static const int THUMB_Y_PADDING = 20;
public static const string BG_COLOR = "#777";
private PhotoTable photoTable = null;
private PhotoTable photoTable = new PhotoTable();
private Gtk.Viewport viewport = new Gtk.Viewport(null, null);
private Gtk.Table layoutTable = new Gtk.Table(0, 0, false);
private Gtk.MenuBar menubar = null;
private Gtk.Toolbar toolbar = new Gtk.Toolbar();
private Gtk.HScale slider = null;
private Gee.ArrayList<Thumbnail> thumbnailList = new Gee.ArrayList<Thumbnail>();
private int currentX = 0;
private int currentY = 0;
......@@ -14,12 +17,56 @@ public class CollectionPage : Gtk.ScrolledWindow {
private int thumbCount = 0;
private int scale = Thumbnail.DEFAULT_SCALE;
// 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 },
{ "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, null },
{ "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 },
{ "Help", null, "_Help", null, null, null },
{ "About", Gtk.STOCK_ABOUT, "_About", null, "About this application", on_about }
};
// 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 }
};
construct {
Gtk.ActionGroup mainActionGroup = new Gtk.ActionGroup("CollectionActionGroup");
mainActionGroup.add_actions(ACTIONS, this);
AppWindow.get_ui_manager().insert_action_group(mainActionGroup, 0);
Gtk.ActionGroup contextActionGroup = new Gtk.ActionGroup("CollectionContextActionGroup");
contextActionGroup.add_actions(RIGHT_CLICK_ACTIONS, this);
AppWindow.get_ui_manager().insert_action_group(contextActionGroup, 0);
// this page's menu bar
menubar = (Gtk.MenuBar) AppWindow.get_ui_manager().get_widget("/CollectionMenuBar");
AppWindow.get_main_window().add_accel_group(AppWindow.get_ui_manager().get_accel_group());
// set up page's toolbar (used by AppWindow for layout)
//
// thumbnail size slider
slider = new Gtk.HScale.with_range(0, scaleToSlider(Thumbnail.MAX_SCALE), 1);
slider.set_value(scaleToSlider(scale));
slider.value_changed += on_slider_changed;
slider.set_draw_value(false);
Gtk.ToolItem toolitem = new Gtk.ToolItem();
toolitem.add(slider);
toolitem.set_expand(false);
toolitem.set_size_request(200, -1);
toolbar.insert(toolitem, -1);
// scrollbar policy
set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
......@@ -27,10 +74,6 @@ public class CollectionPage : Gtk.ScrolledWindow {
layoutTable.set_col_spacings(THUMB_X_PADDING);
layoutTable.set_row_spacings(THUMB_Y_PADDING);
Gtk.ActionGroup actionGroup = new Gtk.ActionGroup("CollectionPageActionGroup");
actionGroup.add_actions(RIGHT_CLICK_ACTIONS, this);
AppWindow.get_ui_manager().insert_action_group(actionGroup, 0);
// need to manually build viewport to set its background color
viewport.add(layoutTable);
viewport.modify_bg(Gtk.StateType.NORMAL, parse_color(BG_COLOR));
......@@ -56,8 +99,12 @@ public class CollectionPage : Gtk.ScrolledWindow {
button_press_event += on_click;
}
public CollectionPage() {
photoTable = new PhotoTable();
public Gtk.Toolbar get_toolbar() {
return toolbar;
}
public Gtk.MenuBar get_menubar() {
return menubar;
}
public void add_photo(PhotoID photoID, File file) {
......@@ -177,24 +224,47 @@ public class CollectionPage : Gtk.ScrolledWindow {
return count;
}
public void increase_thumb_size() {
public int increase_thumb_size() {
if (scale == Thumbnail.MAX_SCALE)
return;
return scale;
scale += Thumbnail.SCALE_STEPPING;
if (scale > Thumbnail.MAX_SCALE) {
scale = Thumbnail.MAX_SCALE;
}
foreach (Thumbnail thumbnail in thumbnailList) {
thumbnail.resize(scale);
}
layoutTable.resize_children();
return scale;
}
public void decrease_thumb_size() {
public int decrease_thumb_size() {
if (scale == Thumbnail.MIN_SCALE)
return;
return scale;
scale -= Thumbnail.SCALE_STEPPING;
if (scale < Thumbnail.MIN_SCALE) {
scale = Thumbnail.MIN_SCALE;
}
foreach (Thumbnail thumbnail in thumbnailList) {
thumbnail.resize(scale);
}
layoutTable.resize_children();
return scale;
}
public void set_thumb_size(int newScale) {
assert(newScale >= Thumbnail.MIN_SCALE);
assert(newScale <= Thumbnail.MAX_SCALE);
scale = newScale;
foreach (Thumbnail thumbnail in thumbnailList) {
thumbnail.resize(scale);
......@@ -220,6 +290,32 @@ public class CollectionPage : Gtk.ScrolledWindow {
return false;
}
private void on_about() {
AppWindow.get_main_window().about_box();
}
private void set_item_sensitive(string path, bool sensitive) {
Gtk.Widget widget = AppWindow.get_ui_manager().get_widget(path);
widget.set_sensitive(sensitive);
}
private void on_edit_menu() {
set_item_sensitive("/CollectionMenuBar/EditMenu/EditSelectAll", get_count() > 0);
set_item_sensitive("/CollectionMenuBar/EditMenu/EditRemove", get_selected_count() > 0);
}
private void on_select_all() {
select_all();
}
private void on_increase_size() {
slider.set_value((increase_thumb_size() - Thumbnail.MIN_SCALE) / Thumbnail.SCALE_STEPPING);
}
private void on_decrease_size() {
slider.set_value((decrease_thumb_size() - Thumbnail.MIN_SCALE) / Thumbnail.SCALE_STEPPING);
}
private bool on_click(CollectionPage c, Gdk.EventButton event) {
switch (event.button) {
case 1:
......@@ -287,7 +383,7 @@ public class CollectionPage : Gtk.ScrolledWindow {
unselect_all();
thumbnail.select();
Gtk.Menu contextMenu = (Gtk.Menu) AppWindow.get_ui_manager().get_widget("/CollectionRightClickMenu");
Gtk.Menu contextMenu = (Gtk.Menu) AppWindow.get_ui_manager().get_widget("/CollectionContextMenu");
contextMenu.popup(null, null, null, event.button, event.time);
return true;
......@@ -339,5 +435,25 @@ public class CollectionPage : Gtk.ScrolledWindow {
//message("%d exposed, %d unexposed", exposedCount, unexposedCount);
}
private double scaleToSlider(int value) {
assert(value >= Thumbnail.MIN_SCALE);
assert(value <= Thumbnail.MAX_SCALE);
return (double) ((value - Thumbnail.MIN_SCALE) / Thumbnail.SCALE_STEPPING);
}
private int sliderToScale(double value) {
int res = ((int) (value * Thumbnail.SCALE_STEPPING)) + Thumbnail.MIN_SCALE;
assert(res >= Thumbnail.MIN_SCALE);
assert(res <= Thumbnail.MAX_SCALE);
return res;
}
private void on_slider_changed() {
set_thumb_size(sliderToScale(slider.get_value()));
}
}
......@@ -9,7 +9,8 @@ public class Thumbnail : Gtk.Alignment {
public static const int MIN_SCALE = 64;
public static const int MAX_SCALE = 360;
public static const int DEFAULT_SCALE = 128;
public static const int SCALE_STEPPING = 4;
// SCALE_STEPPING should divide evenly into (MAX_SCALE - MIN_SCALE)
public static const int SCALE_STEPPING = 8;
public static const Gdk.InterpType DEFAULT_INTERP = Gdk.InterpType.BILINEAR;
// Due to the potential for thousands or tens of thousands of thumbnails being present in a
......
......@@ -162,13 +162,15 @@ public class ThumbnailCache : Object {
debug("Removing [%d] %s", photoID.id, cached.get_path());
ImageData data = cacheMap.get(photoID);
if (cacheMap.contains(photoID)) {
ImageData data = cacheMap.get(photoID);
assert(cachedBytes >= data.buffer.length);
cachedBytes -= data.buffer.length;
assert(cachedBytes >= data.buffer.length);
cachedBytes -= data.buffer.length;
// remove from in-memory cache
cacheMap.remove(photoID);
// remove from in-memory cache
cacheMap.remove(photoID);
}
// remove from db table
cacheTable.remove(photoID);
......
<ui>
<menubar name="MenuBar">
<menubar name="CollectionMenuBar">
<menu name="FileMenu" action="File">
<menuitem name="FileQuit" action="Quit" />
</menu>
......@@ -20,7 +20,7 @@
</menu>
</menubar>
<popup name="CollectionRightClickMenu">
<popup name="CollectionContextMenu">
<menuitem name="Remove" action="Remove" />
</popup>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment