Commit abf4f3c2 authored by Jim Nelson's avatar Jim Nelson

Port to GTK+3: #3455

This enables Shotwell to build and run under GTK+3.  Note there are many outstanding bugs
caused by this move; they will be dealt with in separate commits.
parent 367e2a82
......@@ -262,8 +262,8 @@ LOCAL_PKGS = \
# added to this list
EXT_PKGS = \
atk \
gdk-2.0 \
gdk-x11-2.0 \
gdk-3.0 \
gdk-x11-3.0 \
gee-1.0 \
gexiv2 \
gio-unix-2.0 \
......@@ -272,22 +272,22 @@ EXT_PKGS = \
gstreamer-0.10 \
gstreamer-base-0.10 \
gstreamer-pbutils-0.10 \
gtk+-2.0 \
gtk+-3.0 \
gudev-1.0 \
libexif \
libgphoto2 \
libsoup-2.4 \
libxml-2.0 \
sqlite3 \
unique-1.0 \
webkit-1.0 \
unique-3.0 \
webkitgtk-3.0 \
gconf-2.0
ifdef UNITY_SUPPORT
EXT_PKGS += unity
endif
THUMBNAILER_PKGS = \
gtk+-2.0 \
gtk+-3.0 \
gee-1.0 \
gstreamer-0.10 \
gstreamer-base-0.10
......@@ -307,16 +307,17 @@ EXT_PKG_VERSIONS = \
gmodule-2.0 >= 2.24.0 \
gstreamer-0.10 >= 0.10.28 \
gstreamer-base-0.10 >= 0.10.28 \
gstreamer-plugins-base-0.10 >= 0.10.32 \
gstreamer-pbutils-0.10 >= 0.10.32 \
gtk+-2.0 >= 2.18.0 \
gtk+-3.0 >= 3.0.11 \
gudev-1.0 >= 145 \
libexif >= 0.6.16 \
libgphoto2 >= 2.4.2 \
libsoup-2.4 >= 2.26.0 \
libxml-2.0 >= 2.6.32 \
sqlite3 >= 3.5.9 \
unique-1.0 >= 1.0.0 \
webkit-1.0 >= 1.1.5 \
unique-3.0 >= 3.0.0 \
webkitgtk-3.0 >= 1.4.0 \
gconf-2.0 >= 2.22.0
ifdef ENABLE_TESTS
......
......@@ -44,6 +44,7 @@ all: $(PLUGIN).so
-X -I../.. -X -fPIC \
$(foreach dfn,$(DEFINES),-X $(dfn)) \
$(USER_VALAFLAGS) \
--vapidir=../../vapi \
$(SRC_FILES)
@touch .stamp
......
......@@ -2,10 +2,10 @@
PLUGIN := shotwell-publishing-extras
PKGS := \
gtk+-2.0 \
gtk+-3.0 \
libsoup-2.4 \
libxml-2.0 \
webkit-1.0 \
webkitgtk-3.0 \
gee-1.0
SRC_FILES := \
......
......@@ -1045,10 +1045,10 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, Object {
private Gtk.Builder builder;
private Gtk.RadioButton use_existing_radio;
private Gtk.RadioButton create_new_radio;
private Gtk.ComboBox existing_categories_combo;
private Gtk.ComboBoxText existing_categories_combo;
private Gtk.Entry new_category_entry;
private Gtk.ComboBox perms_combo;
private Gtk.ComboBox size_combo;
private Gtk.ComboBoxText perms_combo;
private Gtk.ComboBoxText size_combo;
private Gtk.Button logout_button;
private Gtk.Button publish_button;
......@@ -1084,10 +1084,10 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, Object {
use_existing_radio = builder.get_object("use_existing_radio") as Gtk.RadioButton;
create_new_radio = builder.get_object("create_new_radio") as Gtk.RadioButton;
existing_categories_combo = builder.get_object("existing_categories_combo") as Gtk.ComboBox;
existing_categories_combo = builder.get_object("existing_categories_combo") as Gtk.ComboBoxText;
new_category_entry = builder.get_object ("new_category_entry") as Gtk.Entry;
perms_combo = builder.get_object("perms_combo") as Gtk.ComboBox;
size_combo = builder.get_object("size_combo") as Gtk.ComboBox;
perms_combo = builder.get_object("perms_combo") as Gtk.ComboBoxText;
size_combo = builder.get_object("size_combo") as Gtk.ComboBoxText;
logout_button = builder.get_object("logout_button") as Gtk.Button;
logout_button.clicked.connect(on_logout_button_clicked);
......
......@@ -133,7 +133,7 @@ internal class WebAuthPane : Spit.Publishing.DialogPane, GLib.Object {
}
private void on_page_load(WebKit.WebFrame origin_frame) {
pane_widget.window.set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
pane_widget.get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
}
private WebKit.NavigationResponse navigation_requested (WebKit.WebFrame frame, WebKit.NetworkRequest req) {
......@@ -145,7 +145,7 @@ internal class WebAuthPane : Spit.Publishing.DialogPane, GLib.Object {
string access_token = info.fetch_all()[2];
debug("Load completed: %s", access_token);
pane_widget.window.set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
pane_widget.get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
if (access_token != null) {
login_succeeded(access_token);
return WebKit.NavigationResponse.IGNORE;
......@@ -156,7 +156,7 @@ internal class WebAuthPane : Spit.Publishing.DialogPane, GLib.Object {
}
private void on_load_started(WebKit.WebFrame frame) {
pane_widget.window.set_cursor(new Gdk.Cursor(Gdk.CursorType.WATCH));
pane_widget.get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.WATCH));
}
public Gtk.Widget get_widget() {
......@@ -189,7 +189,7 @@ internal class PublishingOptionsPane: Spit.Publishing.DialogPane, GLib.Object {
private Gtk.Builder builder;
private Gtk.Button logout_button;
private Gtk.Button publish_button;
private Gtk.ComboBoxEntry album_list;
private Gtk.ComboBoxText album_list;
private weak PublishOptions options;
......@@ -222,7 +222,7 @@ internal class PublishingOptionsPane: Spit.Publishing.DialogPane, GLib.Object {
builder.connect_signals(null);
Gtk.Alignment align = builder.get_object("alignment") as Gtk.Alignment;
album_list = builder.get_object ("album_list") as Gtk.ComboBoxEntry;
album_list = builder.get_object ("album_list") as Gtk.ComboBoxText;
foreach (string key in list.keys)
album_list.append_text(key);
......@@ -253,7 +253,7 @@ internal class PublishingOptionsPane: Spit.Publishing.DialogPane, GLib.Object {
tmp = builder.get_object("disable_comments_check") as Gtk.CheckButton;
options.disable_comments = tmp.active;
Gtk.ComboBoxEntry access_type = builder.get_object("access_type_list") as Gtk.ComboBoxEntry;
Gtk.ComboBoxText access_type = builder.get_object("access_type_list") as Gtk.ComboBoxText;
options.access_type = access_type.get_active_text();
publish();
......
......@@ -62,7 +62,7 @@
</packing>
</child>
<child>
<object class="GtkComboBox" id="existing_categories_combo">
<object class="GtkComboBoxText" id="existing_categories_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
......@@ -111,7 +111,7 @@
</packing>
</child>
<child>
<object class="GtkComboBox" id="perms_combo">
<object class="GtkComboBoxText" id="perms_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
......
......@@ -41,7 +41,7 @@
</object>
</child>
<child>
<object class="GtkComboBoxEntry" id="access_type_list">
<object class="GtkComboBoxText" id="access_type_list">
<property name="visible">True</property>
<property name="model">liststore1</property>
<property name="active">0</property>
......@@ -54,7 +54,7 @@
</packing>
</child>
<child>
<object class="GtkComboBoxEntry" id="album_list">
<object class="GtkComboBoxText" id="album_list">
<property name="visible">True</property>
<property name="model">liststore2</property>
<property name="active">0</property>
......
......@@ -1422,7 +1422,7 @@ internal class WebAuthenticationPane : Spit.Publishing.DialogPane, Object {
}
private void on_page_load(WebKit.WebFrame origin_frame) {
pane_widget.window.set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
pane_widget.get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
string loaded_url = origin_frame.get_uri().dup();
......@@ -1448,7 +1448,7 @@ internal class WebAuthenticationPane : Spit.Publishing.DialogPane, Object {
}
private void on_load_started(WebKit.WebFrame frame) {
pane_widget.window.set_cursor(new Gdk.Cursor(Gdk.CursorType.WATCH));
pane_widget.get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.WATCH));
}
public static bool is_cache_dirty() {
......@@ -1530,7 +1530,7 @@ internal class LegacyPublishingOptionsPane : Gtk.VBox {
private Gtk.RadioButton use_existing_radio = null;
private Gtk.RadioButton create_new_radio = null;
private Gtk.ComboBox existing_albums_combo = null;
private Gtk.ComboBoxText existing_albums_combo = null;
private Gtk.ComboBox visibility_combo = null;
private Gtk.Entry new_album_entry = null;
private Gtk.Button publish_button = null;
......@@ -1601,7 +1601,7 @@ internal class LegacyPublishingOptionsPane : Gtk.VBox {
Gtk.HBox use_existing_layouter = new Gtk.HBox(false, 8);
use_existing_layouter.add(use_existing_radio);
existing_albums_combo = new Gtk.ComboBox.text();
existing_albums_combo = new Gtk.ComboBoxText();
Gtk.Alignment existing_combo_aligner = new Gtk.Alignment(1.0f, 0.5f, 0.0f, 0.0f);
existing_combo_aligner.add(existing_albums_combo);
use_existing_layouter.add(existing_combo_aligner);
......@@ -1722,7 +1722,7 @@ internal class LegacyPublishingOptionsPane : Gtk.VBox {
}
private Gtk.ComboBox create_visibility_combo() {
Gtk.ComboBox result = new Gtk.ComboBox.text();
Gtk.ComboBoxText result = new Gtk.ComboBoxText();
foreach (PrivacyDescription p in privacy_descriptions)
result.append_text(p.description);
......@@ -1732,7 +1732,7 @@ internal class LegacyPublishingOptionsPane : Gtk.VBox {
private Gtk.ComboBox create_resolution_combo() {
Gtk.ComboBox result = new Gtk.ComboBox.text();
Gtk.ComboBoxText result = new Gtk.ComboBoxText();
foreach (Resolution res in possible_resolutions)
result.append_text(res.get_name());
......
......@@ -918,7 +918,7 @@ internal class WebAuthenticationPane : Spit.Publishing.DialogPane, Object {
private void on_load_started(WebKit.WebFrame origin_frame) {
webview.hide();
pane_widget.window.set_cursor(new Gdk.Cursor(Gdk.CursorType.WATCH));
pane_widget.get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.WATCH));
}
public static bool is_cache_dirty() {
......@@ -927,12 +927,12 @@ internal class WebAuthenticationPane : Spit.Publishing.DialogPane, Object {
public void show_page() {
webview.show();
pane_widget.window.set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
pane_widget.get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
}
public void interaction_completed() {
cache_dirty = true;
pane_widget.window.set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
pane_widget.get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
}
public Gtk.Widget get_widget() {
......@@ -1113,7 +1113,7 @@ internal class LegacyPublishingOptionsPane : Gtk.VBox {
}
private Gtk.ComboBox create_visibility_combo() {
Gtk.ComboBox result = new Gtk.ComboBox.text();
Gtk.ComboBoxText result = new Gtk.ComboBoxText();
if (visibilities == null)
visibilities = create_visibilities();
......@@ -1139,7 +1139,7 @@ internal class LegacyPublishingOptionsPane : Gtk.VBox {
}
private Gtk.ComboBox create_size_combo() {
Gtk.ComboBox result = new Gtk.ComboBox.text();
Gtk.ComboBoxText result = new Gtk.ComboBoxText();
if (sizes == null)
sizes = create_sizes();
......
......@@ -2,10 +2,10 @@
PLUGIN := shotwell-publishing
PKGS := \
gtk+-2.0 \
gtk+-3.0 \
libsoup-2.4 \
libxml-2.0 \
webkit-1.0 \
webkitgtk-3.0 \
gexiv2 \
gee-1.0
......
......@@ -1019,10 +1019,10 @@ internal class LegacyPublishingOptionsPane : Gtk.VBox {
private const string DEFAULT_SIZE_CONFIG_KEY = "default_size";
private const string LAST_ALBUM_CONFIG_KEY = "last_album";
private Gtk.ComboBox existing_albums_combo;
private Gtk.ComboBoxText existing_albums_combo;
private Gtk.Entry new_album_entry;
private Gtk.CheckButton public_check;
private Gtk.ComboBox size_combo;
private Gtk.ComboBoxText size_combo;
private Gtk.RadioButton use_existing_radio;
private Gtk.RadioButton create_new_radio;
private Album[] albums;
......@@ -1091,7 +1091,7 @@ internal class LegacyPublishingOptionsPane : Gtk.VBox {
Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 4, 4);
existing_albums_combo = new Gtk.ComboBox.text();
existing_albums_combo = new Gtk.ComboBoxText();
Gtk.Alignment existing_albums_combo_frame = new Gtk.Alignment(0.0f, 0.5f, 0.0f, 0.0f);
existing_albums_combo_frame.add(existing_albums_combo);
main_table.attach(existing_albums_combo_frame, 2, 3, 1, 2,
......@@ -1136,7 +1136,7 @@ internal class LegacyPublishingOptionsPane : Gtk.VBox {
Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 4, 4);
size_combo = new Gtk.ComboBox.text();
size_combo = new Gtk.ComboBoxText();
foreach(SizeDescription desc in size_descriptions)
size_combo.append_text(desc.name);
......
......@@ -949,7 +949,7 @@ internal class LegacyPublishingOptionsPane : Gtk.VBox {
private const int ACTION_BUTTON_SPACING = 48;
private const int STANDARD_ACTION_BUTTON_WIDTH = 128;
private Gtk.ComboBox privacy_combo;
private Gtk.ComboBoxText privacy_combo;
private string channel_name;
private PrivacyDescription[] privacy_descriptions;
private Gtk.Button publish_button;
......@@ -1002,7 +1002,7 @@ internal class LegacyPublishingOptionsPane : Gtk.VBox {
Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 4, 4);
privacy_combo = new Gtk.ComboBox.text();
privacy_combo = new Gtk.ComboBoxText();
foreach(PrivacyDescription desc in privacy_descriptions)
privacy_combo.append_text(desc.description);
privacy_combo.set_active(PrivacySetting.PUBLIC);
......
......@@ -4,6 +4,11 @@
* See the COPYING file in this distribution.
*/
// This is required due to a binding error. This is fixed in 0.13 trunk and can be removed when
// Shotwell is ported to that version of Vala.
extern void gdk_device_get_position(Gdk.Device device, out unowned Gdk.Screen screen,
out int x, out int y);
public class FullscreenWindow : PageWindow {
public const int TOOLBAR_INVOCATION_MSEC = 250;
public const int TOOLBAR_DISMISSAL_SEC = 2;
......@@ -199,9 +204,19 @@ public class FullscreenWindow : PageWindow {
}
private bool is_pointer_in_toolbar() {
int py, wy;
get_display().get_pointer(null, null, out py, null);
toolbar_window.window.get_geometry(null, out wy, null, null, null);
Gdk.DeviceManager? devmgr = get_display().get_device_manager();
if (devmgr == null) {
debug("No device manager for display");
return false;
}
int py;
gdk_device_get_position(devmgr.get_client_pointer(), null, null, out py);
int wy;
toolbar_window.get_window().get_geometry(null, out wy, null, null);
return (py >= wy);
}
......@@ -221,7 +236,7 @@ public class FullscreenWindow : PageWindow {
private void on_toolbar_realized() {
Gtk.Requisition req;
toolbar_window.size_request(out req);
toolbar_window.get_preferred_size(null, out req);
// place the toolbar in the center of the monitor along the bottom edge
Gdk.Rectangle monitor = get_monitor_geometry();
......@@ -380,7 +395,7 @@ public abstract class PageWindow : Gtk.Window {
if (busy_counter++ > 0)
return;
window.set_cursor(new Gdk.Cursor(Gdk.CursorType.WATCH));
get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.WATCH));
spin_event_loop(10);
}
......@@ -392,7 +407,7 @@ public abstract class PageWindow : Gtk.Window {
return;
}
window.set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
spin_event_loop(10);
}
......@@ -712,7 +727,7 @@ public abstract class AppWindow : PageWindow {
}
public void show_uri(string url) throws Error {
sys_show_uri(window.get_screen(), url);
sys_show_uri(get_window().get_screen(), url);
}
protected virtual Gtk.ActionGroup[] create_common_action_groups() {
......@@ -905,7 +920,7 @@ public abstract class AppWindow : PageWindow {
}
public override bool configure_event(Gdk.EventConfigure event) {
maximized = (window.get_state() == Gdk.WindowState.MAXIMIZED);
maximized = (get_window().get_state() == Gdk.WindowState.MAXIMIZED);
if (!maximized)
get_size(out dimensions.width, out dimensions.height);
......
......@@ -783,19 +783,22 @@ public class CheckerboardLayout : Gtk.DrawingArea {
private void on_viewport_resized() {
Gtk.Requisition req;
size_request(out req);
get_preferred_size(null, out req);
Gtk.Allocation parent_allocation;
parent.get_allocation(out parent_allocation);
if (message == null) {
// set the layout's new size to be the same as the parent's width but maintain
// it's own height
#if TRACE_REFLOW
debug("on_viewport_resized: due_to_reflow=%s set_size_request %dx%d",
size_allocate_due_to_reflow.to_string(), parent.allocation.width, req.height);
size_allocate_due_to_reflow.to_string(), parent_allocation.width, req.height);
#endif
set_size_request(parent.allocation.width, req.height);
set_size_request(parent_allocation.width, req.height);
} else {
// set the layout's width and height to always match the parent's
set_size_request(parent.allocation.width, parent.allocation.height);
set_size_request(parent_allocation.width, parent_allocation.height);
}
// possible for this widget's size_allocate not to be called, so need to update the page
......@@ -954,8 +957,12 @@ public class CheckerboardLayout : Gtk.DrawingArea {
if (text != null) {
// message is being set, change size to match parent's; if no parent, then the size
// will be set later when added to the parent
if (parent != null)
set_size_request(parent.allocation.width, parent.allocation.height);
if (parent != null) {
Gtk.Allocation parent_allocation;
parent.get_allocation(out parent_allocation);
set_size_request(parent_allocation.width, parent_allocation.height);
}
} else {
// message is being cleared, layout all the items again
need_reflow("set_message");
......@@ -1048,6 +1055,9 @@ public class CheckerboardLayout : Gtk.DrawingArea {
public Gee.List<CheckerboardItem> intersection(Gdk.Rectangle area) {
Gee.ArrayList<CheckerboardItem> intersects = new Gee.ArrayList<CheckerboardItem>();
Gtk.Allocation allocation;
get_allocation(out allocation);
Gdk.Rectangle bitbucket = Gdk.Rectangle();
foreach (LayoutRow row in item_rows) {
if (row == null)
......@@ -1167,11 +1177,17 @@ public class CheckerboardLayout : Gtk.DrawingArea {
public void set_drag_select_origin(int x, int y) {
clear_drag_select();
Gtk.Allocation allocation;
get_allocation(out allocation);
drag_origin.x = x.clamp(0, allocation.width);
drag_origin.y = y.clamp(0, allocation.height);
}
public void set_drag_select_endpoint(int x, int y) {
Gtk.Allocation allocation;
get_allocation(out allocation);
drag_endpoint.x = x.clamp(0, allocation.width);
drag_endpoint.y = y.clamp(0, allocation.height);
......@@ -1181,7 +1197,7 @@ public class CheckerboardLayout : Gtk.DrawingArea {
selection_band = Box.from_points(drag_origin, drag_endpoint).get_rectangle();
// force repaint of the union of the old and new, which covers the band reducing in size
if (window != null) {
if (get_window() != null) {
Gdk.Rectangle union;
selection_band.union(old_selection_band, out union);
......@@ -1216,14 +1232,14 @@ public class CheckerboardLayout : Gtk.DrawingArea {
update_visible_page();
// only reflow() if the width has changed
if (allocation.width != last_width) {
if (visible_page.width != last_width) {
int old_width = last_width;
last_width = allocation.width;
last_width = visible_page.width;
need_reflow("viewport_resized (%d -> %d)".printf(old_width, allocation.width));
need_reflow("viewport_resized (%d -> %d)".printf(old_width, visible_page.width));
} else {
// don't need to reflow but exposure may have changed
need_exposure("viewport_resized");
need_exposure("viewport_resized (same width=%d)".printf(last_width));
}
}
......@@ -1285,15 +1301,25 @@ public class CheckerboardLayout : Gtk.DrawingArea {
if (message != null)
return;
Gtk.Allocation allocation;
get_allocation(out allocation);
int visible_width = (visible_page.width > 0) ? visible_page.width : allocation.width;
#if TRACE_REFLOW
debug("reflow: Using visible page width of %d (allocated: %d)", visible_width,
allocation.width);
#endif
// don't bother until layout is of some appreciable size (even this is too low)
if (allocation.width <= 1)
if (visible_width <= 1)
return;
int total_items = view.get_count();
// need to set_size in case all items were removed and the viewport size has changed
if (total_items == 0) {
set_size_request(allocation.width, 0);
set_size_request(visible_width, 0);
item_rows = new LayoutRow[0];
return;
......@@ -1316,7 +1342,7 @@ public class CheckerboardLayout : Gtk.DrawingArea {
int max_cols = 0;
if (scale > 0) {
// calculate interior width
int remaining_width = allocation.width - (COLUMN_GUTTER_PADDING * 2);
int remaining_width = visible_width - (COLUMN_GUTTER_PADDING * 2);
int max_item_width = CheckerboardItem.get_max_width(scale);
max_cols = remaining_width / max_item_width;
if (max_cols <= 0)
......@@ -1354,7 +1380,7 @@ public class CheckerboardLayout : Gtk.DrawingArea {
assert(req.has_area());
// carriage return (i.e. this item will overflow the view)
if ((x + req.width + COLUMN_GUTTER_PADDING) > allocation.width) {
if ((x + req.width + COLUMN_GUTTER_PADDING) > visible_width) {
if (row_width > widest_row) {
widest_row = row_width;
max_cols = col;
......@@ -1441,7 +1467,7 @@ public class CheckerboardLayout : Gtk.DrawingArea {
// Step 3: Calculate the gutter between the items as being equidistant of the
// remaining space (adding one gutter to account for the right-hand one)
gutter = (allocation.width - total_width) / (max_cols + 1);
gutter = (visible_width - total_width) / (max_cols + 1);
// if only one column, gutter size could be less than minimums
if (max_cols == 1)
......@@ -1456,7 +1482,7 @@ public class CheckerboardLayout : Gtk.DrawingArea {
#if TRACE_REFLOW
debug("reflow %s: readjusting columns: alloc.width=%d total_width=%d widest=%d gutter=%d max_cols now=%d",
page_name, allocation.width, total_width, widest, gutter, max_cols);
page_name, visible_width, total_width, widest, gutter, max_cols);
#endif
col = 0;
......@@ -1474,7 +1500,7 @@ public class CheckerboardLayout : Gtk.DrawingArea {
}
#if TRACE_REFLOW
debug("reflow %s: width:%d total_width:%d max_cols:%d gutter:%d", page_name, allocation.width,
debug("reflow %s: width:%d total_width:%d max_cols:%d gutter:%d", page_name, visible_width,
total_width, max_cols, gutter);
#endif
......@@ -1566,21 +1592,20 @@ public class CheckerboardLayout : Gtk.DrawingArea {
rows = row + 1;
assert(rows == max_rows);
// Step 6: Define the total size of the page as the size of the allocated width and
// the height of all the items plus padding
// Step 6: Define the total size of the page as the size of the visible width (to avoid
// the horizontal scrollbar from appearing) and the height of all the items plus padding
int total_height = y + row_heights[row] + BOTTOM_PADDING;
if (total_height != allocation.height) {
if (visible_width != allocation.width || total_height != allocation.height) {
#if TRACE_REFLOW
debug("reflow %s: Changing layout dimensions from %dx%d to %dx%d", page_name,
allocation.width, allocation.height, allocation.width, total_height);
allocation.width, allocation.height, visible_width, total_height);
#endif
set_size_request(allocation.width, total_height);
set_size_request(visible_width, total_height);
size_allocate_due_to_reflow = true;
// when height changes, center on the anchor to minimize amount of visual change
center_on_anchor(total_height);
}
}
private void items_dirty(string reason, Gee.Iterable<DataView> items) {
......@@ -1631,11 +1656,11 @@ public class CheckerboardLayout : Gtk.DrawingArea {
private void set_colors(bool in_focus = true) {
// set up selected/unselected colors
selected_color = fetch_color(
Config.Facade.get_instance().get_selected_color(in_focus).to_string(), window);
Config.Facade.get_instance().get_selected_color(in_focus).to_string());
unselected_color = fetch_color(
Config.Facade.get_instance().get_unselected_color().to_string(), window);
Config.Facade.get_instance().get_unselected_color().to_string());
border_color = fetch_color(
Config.Facade.get_instance().get_border_color().to_string(), window);
Config.Facade.get_instance().get_border_color().to_string());
bg_color = this.get_style().bg[Gtk.StateType.NORMAL];
}
......@@ -1645,28 +1670,25 @@ public class CheckerboardLayout : Gtk.DrawingArea {
viewport_resized();
}
public override bool expose_event(Gdk.EventExpose event) {
// Note: It's possible for expose_event to be called when in_view is false; this happens
public override bool draw(Cairo.Context ctx) {
// Note: It's possible for draw to be called when in_view is false; this happens
// when pages are switched prior to switched_to() being called, and some of the other
// controls allow for events to be processed while they are orienting themselves. Since
// we want switched_to() to be the final call in the process (indicating that the page is
// now in place and should do its thing to update itself), have to be be prepared for
// GTK/GDK calls between the widgets being actually present on the screen and "switched to"
// switch to Cairo
Cairo.Context ctx = Gdk.cairo_create(event.window);
// watch for message mode
if (message == null) {
#if TRACE_REFLOW
debug("expose_event %s: %s", page_name, rectangle_to_string(event.area));
debug("draw %s: %s", page_name, rectangle_to_string(visible_page));
#endif
if (exposure_dirty)
expose_items("expose_event");
expose_items("draw");
// have all items in the exposed area paint themselves
foreach (CheckerboardItem item in intersection(event.area)) {
foreach (CheckerboardItem item in intersection(visible_page)) {
item.paint(ctx, bg_color, item.is_selected() ? selected_color : unselected_color,
unselected_color, border_color);
}
......@@ -1676,6 +1698,9 @@ public class CheckerboardLayout : Gtk.DrawingArea {
int text_width, text_height;
pango_layout.get_pixel_size(out text_width, out text_height);
Gtk.Allocation allocation;
get_allocation(out allocation);
int x = allocation.width - text_width;
x = (x > 0) ? x / 2 : 0;
......@@ -1687,7 +1712,7 @@ public class CheckerboardLayout : Gtk.DrawingArea {
Pango.cairo_show_layout(ctx, pango_layout);
}
bool result = (base.expose_event != null) ? base.expose_event(event) : true;
bool result = (base.draw != null) ? base.draw(ctx) : true;
// draw the selection band last, so it appears floating over everything else
draw_selection_band(ctx);
......
......@@ -216,7 +216,6 @@ public class RGBHistogramManipulator : Gtk.DrawingArea {
private int track_nub_start_position = 0;
public RGBHistogramManipulator( ) {
expose_event.connect(on_expose);
set_size_request(CONTROL_WIDTH, CONTROL_HEIGHT);
if (dummy_slider == null)