~zanneth/hirogen

d54cf10d553dbf71361ab974e155811571fd8ab0 — Charles Magahern 2 years ago 8da38e7
Implement 'find next' and 'find previous'
2 files changed, 107 insertions(+), 33 deletions(-)

M res/main.ui
M src/document_window.rs
M res/main.ui => res/main.ui +20 -0
@@ 226,6 226,26 @@
                        <accelerator key="f" signal="activate" modifiers="GDK_CONTROL_MASK"/>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label" translatable="yes">Find Next</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="action_name">win.find-next</property>
                        <property name="use_stock">False</property>
                        <accelerator key="g" signal="activate" modifiers="GDK_CONTROL_MASK"/>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label" translatable="yes">Find Previous</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="action_name">win.find-prev</property>
                        <property name="use_stock">False</property>
                        <accelerator key="g" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
                      </object>
                    </child>
                  </object>
                </child>
              </object>

M src/document_window.rs => src/document_window.rs +87 -33
@@ 40,13 40,14 @@ use crate::gdk_additions::{Direction, EventKeyExt};
use crate::goto::*;
use crate::guard_unwrap;

#[derive(Copy, Clone, Debug)]
#[derive(Clone, Debug)]
struct State
{
    scroll_velocity:    f64,
    timer_active:       bool,
    editing_byte:       bool,
    adjustment_dirty:   bool,
    scroll_velocity:        f64,
    timer_active:           bool,
    editing_byte:           bool,
    adjustment_dirty:       bool,
    last_find_directive:    Option<FindDirective>,
}

#[derive(Debug)]


@@ 98,10 99,11 @@ impl DocumentWindow

            document:   RefCell::new(Document::new()),
            state:      RefCell::new(State {
                scroll_velocity:    0.0,
                timer_active:       false,
                editing_byte:       false,
                adjustment_dirty:   true,
                scroll_velocity:        0.0,
                timer_active:           false,
                editing_byte:           false,
                adjustment_dirty:       true,
                last_find_directive:    None,
            })
        })
    }


@@ 133,8 135,10 @@ impl DocumentWindow
        self.reload_window_title();
        
        // request adjustment to reload
        let mut state = self.state.borrow_mut();
        state.adjustment_dirty = true;
        {
            let mut state = self.state.borrow_mut();
            state.adjustment_dirty = true;
        }
        
        // scroll to the top
        self.hex_adjustment.set_value(0.0);


@@ 223,6 227,8 @@ impl DocumentWindow
        self.connect_simple_action("delete",     Self::handle_delete_action);
        self.connect_simple_action("select-all", Self::handle_select_all_action);
        self.connect_simple_action("find",       Self::handle_find_action);
        self.connect_simple_action("find-next",  Self::handle_find_next_action);
        self.connect_simple_action("find-prev",  Self::handle_find_prev_action);
        self.connect_simple_action("go-to",      Self::handle_goto_action);
        self.connect_simple_action("about",      Self::handle_about_action);
        


@@ 509,33 515,37 @@ impl DocumentWindow
    fn handle_find_action(self: &DocumentWindowRef)
    {
        let dialog = FindDialog::new(&self.window.clone().upcast::<gtk::Window>());
        let scroll_and_redraw = match dialog.run() {
        match dialog.run() {
            Some(directive) => {
                let mut document = self.document.borrow_mut();
                match document.find(&directive) {
                    Some(loc) => {
                        let begin = loc.byte_offset;
                        document.selection = Some(DocumentSelection {
                            byte_range: begin .. begin + directive.needle.len(),
                            region:     loc.region
                        });
                        
                        true
                    },

                    None => {
                        self.show_dialog_msg(gtk::MessageType::Info, "No results.");
                        false
                    }
                let found_result = self.handle_find(&directive);
                if !found_result {
                    self.show_dialog_msg(gtk::MessageType::Info, "No results.");
                }
            },
            
            None => false
            None => ()
        };
        
        if scroll_and_redraw {
            self.scroll_to_selection();
            self.hex_view_queue_redraw();
    }
    
    fn handle_find_next_action(self: &DocumentWindowRef)
    {
        let directive = self.state.borrow().last_find_directive.clone();
        if let Some(directive) = &directive {
            let mut directive_copy = directive.clone();
            directive_copy.direction = FindDirection::Forward;

            self.handle_find(&directive_copy);
        }
    }

    fn handle_find_prev_action(self: &DocumentWindowRef)
    {
        let directive = self.state.borrow().last_find_directive.clone();
        if let Some(directive) = &directive {
            let mut directive_copy = directive.clone();
            directive_copy.direction = FindDirection::Backward;

            self.handle_find(&directive_copy);
        }
    }
    


@@ 975,6 985,39 @@ impl DocumentWindow
            }
        } 
    }
    
    fn handle_find(self: &DocumentWindowRef, directive: &FindDirective) -> bool
    {
        let found_result_and_updated_sel = {
            let mut document = self.document.borrow_mut();
            match document.find(directive) {
                Some(loc) => {
                    let begin = loc.byte_offset;
                    document.selection = Some(DocumentSelection {
                        byte_range: begin .. begin + directive.needle.len(),
                        region:     loc.region
                    });
                    
                    let mut state = self.state.borrow_mut();
                    state.last_find_directive = Some(directive.clone());
                    
                    true
                },

                None => {
                    false
                }
            }
        };
        
        if found_result_and_updated_sel {
            self.scroll_to_selection();
            self.reload_actions_state();
            self.hex_view_queue_redraw();
        }
        
        found_result_and_updated_sel
    }

    fn scroll_page(self: &DocumentWindowRef, direction: &Direction)
    {


@@ 1078,11 1121,22 @@ impl DocumentWindow
            self.lookup_simple_action("select-all"),
            self.lookup_simple_action("go-to"),
            self.lookup_simple_action("find"),
            self.lookup_simple_action("find-next"),
            self.lookup_simple_action("find-prev"),
        ];
        for document_dependent_action in &document_dependent_actions {
            document_dependent_action.set_enabled(self.has_open_document());
        }
        
        let state = self.state.borrow();
        let find_again_actions = [
            self.lookup_simple_action("find-next"),
            self.lookup_simple_action("find-prev"),
        ];
        for find_again_action in &find_again_actions {
            find_again_action.set_enabled(state.last_find_directive.is_some());
        }
        
        let editing_actions_available = document.selection.is_some();
        let editing_actions = [
            self.lookup_simple_action("cut"),