Skip to content

Commit ec9c050

Browse files
committed
Add split chart ability.
1 parent 3edaa60 commit ec9c050

File tree

4 files changed

+103
-157
lines changed

4 files changed

+103
-157
lines changed

lognplotgtk/src/gui.glade

Lines changed: 4 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -368,14 +368,6 @@
368368
<property name="use_underline">True</property>
369369
</object>
370370
</child>
371-
<child>
372-
<object class="GtkMenuItem" id="menu_new_grid_plot_window">
373-
<property name="visible">True</property>
374-
<property name="can_focus">False</property>
375-
<property name="label" translatable="yes">New 2x2 plot window</property>
376-
<property name="use_underline">True</property>
377-
</object>
378-
</child>
379371
</object>
380372
</child>
381373
</object>
@@ -553,88 +545,14 @@
553545
</packing>
554546
</child>
555547
<child>
556-
<object class="GtkBox" id="root_splittor_box">
548+
<object class="GtkBox" id="root_splittor">
557549
<property name="visible">True</property>
558550
<property name="can_focus">False</property>
551+
<property name="hexpand">True</property>
552+
<property name="vexpand">True</property>
559553
<property name="orientation">vertical</property>
560554
<child>
561-
<object class="GtkDrawingArea" id="chart_control">
562-
<property name="width_request">200</property>
563-
<property name="height_request">200</property>
564-
<property name="visible">True</property>
565-
<property name="can_focus">True</property>
566-
<property name="has_focus">True</property>
567-
<property name="is_focus">True</property>
568-
<property name="can_default">True</property>
569-
<property name="has_default">True</property>
570-
<property name="receives_default">True</property>
571-
<property name="events">GDK_EXPOSURE_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK</property>
572-
</object>
573-
<packing>
574-
<property name="expand">True</property>
575-
<property name="fill">True</property>
576-
<property name="position">0</property>
577-
</packing>
578-
</child>
579-
<child>
580-
<object class="GtkDrawingArea" id="chart_control2">
581-
<property name="width_request">200</property>
582-
<property name="height_request">200</property>
583-
<property name="can_focus">True</property>
584-
<property name="has_focus">True</property>
585-
<property name="is_focus">True</property>
586-
<property name="can_default">True</property>
587-
<property name="has_default">True</property>
588-
<property name="receives_default">True</property>
589-
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK</property>
590-
</object>
591-
<packing>
592-
<property name="expand">True</property>
593-
<property name="fill">True</property>
594-
<property name="position">1</property>
595-
</packing>
596-
</child>
597-
<child>
598-
<object class="GtkBox">
599-
<property name="visible">True</property>
600-
<property name="can_focus">False</property>
601-
<child>
602-
<object class="GtkButton" id="button_split_vertical">
603-
<property name="label" translatable="yes">Split vertical</property>
604-
<property name="visible">True</property>
605-
<property name="sensitive">False</property>
606-
<property name="can_focus">True</property>
607-
<property name="receives_default">True</property>
608-
</object>
609-
<packing>
610-
<property name="expand">False</property>
611-
<property name="fill">True</property>
612-
<property name="position">0</property>
613-
</packing>
614-
</child>
615-
<child>
616-
<object class="GtkButton" id="button_split_horizontal">
617-
<property name="label" translatable="yes">Split horizontal</property>
618-
<property name="visible">True</property>
619-
<property name="sensitive">False</property>
620-
<property name="can_focus">True</property>
621-
<property name="receives_default">True</property>
622-
</object>
623-
<packing>
624-
<property name="expand">False</property>
625-
<property name="fill">True</property>
626-
<property name="position">1</property>
627-
</packing>
628-
</child>
629-
<child>
630-
<placeholder/>
631-
</child>
632-
</object>
633-
<packing>
634-
<property name="expand">False</property>
635-
<property name="fill">True</property>
636-
<property name="position">2</property>
637-
</packing>
555+
<placeholder/>
638556
</child>
639557
</object>
640558
<packing>

lognplotgtk/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ pub use state::{GuiState, GuiStateHandle};
2828
mod io {
2929
use super::GuiStateHandle;
3030

31-
pub fn save_data_as_hdf5(top_level: &gtk::Window, app_state: &GuiStateHandle) {
31+
pub fn save_data_as_hdf5(_top_level: &gtk::Window, _app_state: &GuiStateHandle) {
3232
unimplemented!();
3333
}
3434

35-
pub fn load_data_from_hdf5(top_level: &gtk::Window, app_state: &GuiStateHandle) {
35+
pub fn load_data_from_hdf5(_top_level: &gtk::Window, _app_state: &GuiStateHandle) {
3636
unimplemented!();
3737
}
3838
}

lognplotgtk/src/mainwindow.rs

Lines changed: 96 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -49,30 +49,95 @@ fn build_ui(app: &gtk::Application, app_state: GuiStateHandle) {
4949
window.show_all();
5050
}
5151

52-
fn setup_chart_area(builder: &gtk::Builder, app_state: GuiStateHandle) {
53-
// First chart:
54-
let draw_area: gtk::DrawingArea = builder.get_object("chart_control").unwrap();
55-
let chart_state1 = setup_drawing_area(draw_area, app_state.clone(), "chart1");
52+
/// Create new chart area with extra buttons around it
53+
/// to enable splitting in vertical and horizontal direction
54+
fn create_new_chart_area(app_state: &GuiStateHandle, parent_box: gtk::Box) {
55+
let box1 = gtk::Box::new(gtk::Orientation::Vertical, 0);
56+
let draw_area: gtk::DrawingArea = gtk::DrawingArea::new();
57+
massage_drawing_area(&draw_area);
58+
box1.pack_start(&draw_area, true, true, 0);
59+
60+
// generate new unique chart id based on amount of charts so far:
61+
let chart_id = format!("chart{}", app_state.borrow().num_charts() + 1);
62+
63+
let chart_state1 = setup_drawing_area(draw_area, app_state.clone(), &chart_id);
5664
app_state.borrow_mut().add_chart(chart_state1);
5765

58-
// Second chart:
59-
let draw_area2: gtk::DrawingArea = builder.get_object("chart_control2").unwrap();
60-
let chart_state2 = setup_drawing_area(draw_area2, app_state.clone(), "chart2");
61-
app_state.borrow_mut().add_chart(chart_state2);
62-
63-
// Split handler:
64-
// TODO:
65-
// let hbx: gtk::Box = builder.get_object("root_splittor_box").unwrap();
66-
// let split_button: gtk::Button = builder.get_object("button_split_vertical").unwrap();
67-
// split_button.connect_clicked(move |_| {
68-
// println!("Split!");
69-
// hbx.remove(&draw_area2);
70-
// let paned = gtk::Paned::new(gtk::Orientation::Vertical);
71-
// hbx.add(&paned);
72-
// paned.add(&draw_area2);
73-
74-
// // hbx.add_widget(draw_area2);
75-
// });
66+
// Create split buttons:
67+
let box2 = gtk::Box::new(gtk::Orientation::Horizontal, 0);
68+
let button1 = gtk::Button::new();
69+
button1.set_label("Split vertical");
70+
box2.pack_start(&button1, false, false, 0);
71+
72+
let button2 = gtk::Button::new();
73+
button2.set_label("Split horizontal");
74+
box2.pack_start(&button2, false, false, 0);
75+
76+
box1.pack_start(&box2, false, false, 0);
77+
box1.show_all();
78+
79+
button1.connect_clicked(
80+
clone!(@strong app_state, @strong box1, @strong parent_box => move |_| {
81+
info!("Split vertically");
82+
split_chart(&app_state, &box1, gtk::Orientation::Vertical);
83+
}),
84+
);
85+
86+
button2.connect_clicked(
87+
clone!(@strong app_state, @strong box1, @strong parent_box => move |_| {
88+
info!("Split horizontally");
89+
split_chart(&app_state, &box1, gtk::Orientation::Horizontal);
90+
}),
91+
);
92+
93+
parent_box.pack_start(&box1, true, true, 0);
94+
}
95+
96+
/// Complex way of finding position of box in parent box:
97+
fn find_index(box1: gtk::Box, parent: &gtk::Box) -> i32 {
98+
for (index, child) in parent.get_children().iter().enumerate() {
99+
let child_box: gtk::Box = child.clone().downcast::<gtk::Box>().unwrap();
100+
if child_box == box1 {
101+
return index as i32;
102+
}
103+
}
104+
105+
0
106+
}
107+
108+
/// Takes care of splitting the chart into two areas
109+
/// This is done by determining the containing box parent,
110+
/// and removing this box from the parent, placing a new
111+
/// box in between in the box hierarchy..
112+
fn split_chart(app_state: &GuiStateHandle, box1: &gtk::Box, orientation: gtk::Orientation) {
113+
// Create new split pane:
114+
let new_box = gtk::Box::new(orientation, 0);
115+
116+
// Determine parent box (either vertical or horizontal)
117+
let parent_box: gtk::Box = box1.get_parent().unwrap().downcast::<gtk::Box>().unwrap();
118+
119+
// find position in parent:
120+
let index = find_index(box1.clone(), &parent_box);
121+
info!("Old position: {:?}", index);
122+
123+
// Remove original container and add new box:
124+
parent_box.remove(box1);
125+
parent_box.pack_start(&new_box, true, true, 0);
126+
parent_box.reorder_child(&new_box, index); // move to first position again!
127+
128+
new_box.pack_start(box1, true, true, 0);
129+
130+
// create new chart area:
131+
create_new_chart_area(&app_state, new_box.clone());
132+
133+
new_box.show_all();
134+
}
135+
136+
fn setup_chart_area(builder: &gtk::Builder, app_state: GuiStateHandle) {
137+
let root_splittor: gtk::Box = builder.get_object("root_splittor").unwrap();
138+
139+
// Initial chart:
140+
create_new_chart_area(&app_state, root_splittor);
76141
}
77142

78143
fn setup_about_dialog(about_dialog: &gtk::AboutDialog) {
@@ -87,8 +152,8 @@ fn setup_about_dialog(about_dialog: &gtk::AboutDialog) {
87152
about_dialog.connect_response(|p, _| p.hide());
88153
}
89154

90-
/// Construct new plot window with the given number of plots.
91-
fn new_plot_window(app_state: GuiStateHandle, amount: usize) {
155+
/// Construct new plot window.
156+
fn new_plot_window(app_state: GuiStateHandle) {
92157
info!("New window!");
93158
let chart_id = format!("chart{}", app_state.borrow().num_charts() + 1);
94159
let new_window = gtk::WindowBuilder::new()
@@ -99,47 +164,15 @@ fn new_plot_window(app_state: GuiStateHandle, amount: usize) {
99164
new_window.set_icon(Some(&icon));
100165
}
101166

102-
let mut charts = vec![];
103-
if amount > 1 {
104-
let grid = gtk::Grid::new();
105-
new_window.add(&grid);
106-
107-
// Create grid of plots:
108-
for row in 0_i32..amount as i32 {
109-
for column in 0_i32..amount as i32 {
110-
let chart_id = format!(
111-
"chart{}",
112-
app_state.borrow().num_charts() + 1 + charts.len()
113-
);
114-
// println!("Row: {}", row);
115-
let new_chart_area = gtk::DrawingArea::new();
116-
grid.attach(&new_chart_area, column, row, 1, 1);
117-
massage_drawing_area(&new_chart_area);
118-
119-
let chart_n = setup_drawing_area(new_chart_area, app_state.clone(), &chart_id);
120-
charts.push(chart_n);
121-
}
122-
}
123-
124-
grid.show();
125-
} else {
126-
let new_chart_area = gtk::DrawingArea::new();
127-
new_window.add(&new_chart_area);
128-
massage_drawing_area(&new_chart_area);
129-
130-
let chart_n = setup_drawing_area(new_chart_area, app_state.clone(), &chart_id);
131-
charts.push(chart_n);
132-
}
167+
let root_box = gtk::Box::new(gtk::Orientation::Vertical, 0);
168+
new_window.add(&root_box);
133169

134-
for chart_n in &charts {
135-
app_state.borrow_mut().add_chart(chart_n.clone());
136-
}
170+
create_new_chart_area(&app_state, root_box);
137171

138172
new_window.connect_delete_event(clone!(@strong app_state => move |_, _| {
139173
// Remove all chart structs from the app state:
140-
for chart_n in &charts {
141-
app_state.borrow_mut().delete_chart(&chart_n);
142-
}
174+
// TODO: remove charts of this window!
175+
// TODO: by not doing this, we suffer from some memory leakage?
143176
Inhibit(false)
144177
}));
145178
new_window.show_all();
@@ -150,6 +183,7 @@ fn massage_drawing_area(new_chart_area: &gtk::DrawingArea) {
150183
new_chart_area.show();
151184
new_chart_area.set_hexpand(true);
152185
new_chart_area.set_vexpand(true);
186+
new_chart_area.set_size_request(200, 200);
153187

154188
new_chart_area.set_can_focus(true);
155189
new_chart_area.set_can_default(true);
@@ -181,13 +215,7 @@ fn setup_menus(builder: &gtk::Builder, app_state: GuiStateHandle) {
181215

182216
let menu_new_plot_window: gtk::MenuItem = builder.get_object("menu_new_plot_window").unwrap();
183217
menu_new_plot_window.connect_activate(clone!(@strong app_state => move |_| {
184-
new_plot_window(app_state.clone(), 1);
185-
}));
186-
187-
let menu_new_grid_plot_window: gtk::MenuItem =
188-
builder.get_object("menu_new_grid_plot_window").unwrap();
189-
menu_new_grid_plot_window.connect_activate(clone!(@strong app_state => move |_| {
190-
new_plot_window(app_state.clone(), 2);
218+
new_plot_window(app_state.clone());
191219
}));
192220

193221
let top_level: gtk::Window = builder.get_object("top_unit").unwrap();

lognplotgtk/src/state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl GuiState {
5151
}
5252

5353
#[cfg(not(feature = "hdf5"))]
54-
pub fn load(&self, filename: &Path) -> Result<(), String> {
54+
pub fn load(&self, _filename: &Path) -> Result<(), String> {
5555
Err("No hdf5 support!".to_owned())
5656
}
5757

0 commit comments

Comments
 (0)