valagenie

Passing information between classes in a behaviour oriented design


I decided to adapt my small text editor to the behaviour design pattern suggested in a previous question. It was soon clear how the behaviour design could help scale my little project by allowing adding key combinations to call the opening, saving actions and so on.

However, this design mainly uses classes and I am not sure how to make the classes communicate. A new class was added to handle saving the current file (SaveFile), but I am not being able to capture the URI of the current file (that was taken with the DocumentFileSelector class).

My suspicion is that the way to do that is through class properties, but I am not being able to actually make the document_selector variable inherit that property, so I could pass it to the SaveDocument class.

Here is the relevant part of the code:

uses
    Gtk

init
    Intl.setlocale()
    Gtk.init (ref args)

    var document = new Text( "Lorem Ipsum" )

    var header = new Header ( "My text editor" )
    var body = new DocumentView( document )
    var editor = new EditorWindow (header,body )

    var document_selector = new DocumentFileSelector( editor )
    var load_new_content_command = new Load( document, document_selector )
    var create_new = new CreateNew( document )
    var save_file = new SaveFile( document )

    header.add_item( new OpenButton( load_new_content_command ) )
    header.add_item( new CreateNewButton ( create_new ) )
    header.add_item( new SaveFileButton( save_file ))

    editor.show_all ()
    Gtk.main ()

class EditorWindow:Window

    construct( header:Header, body:DocumentView )
        this.window_position = WindowPosition.CENTER
        this.set_default_size( 400, 400 )
        this.destroy.connect( Gtk.main_quit)
        this.set_titlebar(header)
        var box  = new Box (Gtk.Orientation.VERTICAL, 1)
        box.pack_start(body, true, true, 0)
        this.add(box)

class Header:HeaderBar
    construct( title:string = "" )
        this.show_close_button = true
        this.set_title( title )

    def add_item( item:Widget )
        this.pack_start( item )

class SaveFileButton:ToolButton
    construct( command:Command )
        this.icon_widget = new Image.from_icon_name(
                                                 "document-save",
                                                 IconSize.SMALL_TOOLBAR
                                                 )
        this.clicked.connect( command.execute )

class OpenButton:ToolButton
    construct( command:Command )
        this.icon_widget = new Image.from_icon_name(
                                                 "document-open",
                                                 IconSize.SMALL_TOOLBAR
                                                 )
        this.clicked.connect( command.execute )

class CreateNewButton:ToolButton
    construct( command:Command )
        this.icon_widget = new Image.from_icon_name(
                                                 "document-new",
                                                 IconSize.SMALL_TOOLBAR
                                                 )
        this.clicked.connect( command.execute )

class DocumentView:ScrolledWindow
    construct( document:TextBuffer )
        var view = new TextView.with_buffer( document )
        view.set_wrap_mode( Gtk.WrapMode.WORD )
        this.add( view )

interface Command:Object
    def abstract execute()

interface DocumentSelector:Object
    def abstract select():bool
    def abstract get_document():string

class Text:TextBuffer
    construct ( initial:string = "" )
        this.text = initial

class SaveFile:Object implements Command

    _receiver:TextBuffer

    construct( receiver:TextBuffer )
        _receiver = receiver

    def execute()
        start, end : Gtk.TextIter
        _receiver.get_start_iter(out start)
        _receiver.get_end_iter(out end)
        try
            FileUtils.set_contents (_filename, _receiver.get_text(start, end,
            false))
        except ex : FileError
            print "%s\n", ex.message


class DocumentFileSelector:Object implements DocumentSelector

    _parent:Window
    _uri:string = ""

    construct( parent:Window )
        _parent = parent

    def select():bool
        var dialog = new FileChooserDialog( "Open file",
                                            _parent,
                                            FileChooserAction.OPEN,
                                            dgettext( "gtk30", "_OK"),
                                            ResponseType.ACCEPT,
                                            dgettext( "gtk30", "_Cancel" ),
                                            ResponseType.CANCEL
                                           )

        selected:bool = false
        var response = dialog.run()
        case response
            when ResponseType.ACCEPT
                _uri = dialog.get_uri()
                selected = true

        dialog.destroy()
        return selected

    def get_document():string
        return "Reading the text from a URI is not implemented\n%s".printf(_uri)

class Load:Object implements Command

    _receiver:TextBuffer
    _document_selector:DocumentSelector

    construct( receiver:TextBuffer, document_selector:DocumentSelector )
        _receiver = receiver
        _document_selector = document_selector

    def execute()
        if _document_selector.select()
            _receiver.text = _document_selector.get_document()


class CreateNew:Object implements Command

    _receiver:TextBuffer

    construct( receiver:TextBuffer )
        _receiver = receiver

    def execute()
        var should_I_save=new MessageDialog (null, Gtk.DialogFlags.MODAL,
        Gtk.MessageType.INFO, Gtk.ButtonsType.YES_NO, "Hello world!")
        should_I_save.format_secondary_text (
        "This will delete the contets. Are you sure?")

        case should_I_save.run()
            when ResponseType.YES
                _receiver.set_text("")
                should_I_save.destroy ()
            when ResponseType.NO
                should_I_save.destroy ()

Question

Edit

Still couldn't solve the problem, something I recently tried was to create another method inside DocumentFileSelector class called whichFile(). This method would only return the uri. I am getting the error at execution: FileUtils.set_contents ( DocumentFileSelector.whichFile(), _receiver.get_text(start, end,false)).

And here are the modifications to the code:

class SaveFile:Object implements Command

    _receiver:TextBuffer

    construct( receiver:TextBuffer )
        _receiver = receiver

    def execute()
        start, end : Gtk.TextIter
        _receiver.get_start_iter(out start)
        _receiver.get_end_iter(out end)
        try
            FileUtils.set_contents ( DocumentFileSelector.whichFile(), _receiver.get_text(start, end,false))
        except ex : FileError
            print "%s\n", ex.message


class DocumentFileSelector:Object implements DocumentSelector

    _parent:Window
    _uri:string = ""

    construct( parent:Window )
        _parent = parent

    def select():bool
        var dialog = new FileChooserDialog( "Open file",
                                            _parent,
                                            FileChooserAction.OPEN,
                                            dgettext( "gtk30", "_OK"),
                                            ResponseType.ACCEPT,
                                            dgettext( "gtk30", "_Cancel" ),
                                            ResponseType.CANCEL
                                           )

        selected:bool = false
        var response = dialog.run()
        case response
            when ResponseType.ACCEPT
                _uri = dialog.get_uri()
                selected = true

        dialog.destroy()
        return selected

    def whichFile():string
        return _uri

    def get_document():string
        return "Reading the text from a URI is not implemented\n%s".printf(_uri)

Solution

  • You're almost there ...

    Just add a reference to the DocumentSelector to your SaveFile command as you did for the LoadFile command:

    class SaveFile:Object implements Command
        _receiver:TextBuffer
        _document_selector:DocumentSelector
    
        construct( receiver:TextBuffer, document_selector:DocumentSelector)
            _receiver = receiver
            _document_selector = document_selector
    

    You can then invoke your new whichFile() method on the saved DocumentSelector:

    def execute()
        start, end : Gtk.TextIter
        _receiver.get_start_iter(out start)
        _receiver.get_end_iter(out end)
        try
            FileUtils.set_contents (_document_selector.whichFile(), _receiver.get_text(start, end,
            false))
        except ex : FileError
            print "%s\n", ex.message