chart_simul_controler.py 23.5 KB
Newer Older
VIGNET Pierre's avatar
VIGNET Pierre committed
1 2 3
## Filename    : chart_simul_controler.py
## Author(s)   : Michel Le Borgne
## Created     : 04/2010
4 5
## Revision    :
## Source      :
VIGNET Pierre's avatar
VIGNET Pierre committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
##
## Copyright 2012 : IRISA/IRSET
##
## This library is free software; you can redistribute it and/or modify it
## under the terms of the GNU General Public License  published
## by the Free Software Foundation; either version 2.1 of the License, or
## any later version.
##
## This library is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF
## MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  The software and
## documentation provided here under is on an "as is" basis, and IRISA has
## no obligations to provide maintenance, support, updates, enhancements
## or modifications.
## In no event shall IRISA be liable to any party for direct, indirect,
## special, incidental or consequential damages, including lost profits,
## arising out of the use of this software and its documentation, even if
## IRISA have been advised of the possibility of such damage.  See
## the GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this library; if not, write to the Free Software Foundation,
## Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## The original code contained here was initially developed by:
##
##     Michel Le Borgne.
##     IRISA
##     Symbiose team
##     IRISA  Campus de Beaulieu
36 37
##     35042 RENNES Cedex, FRANCE
##
VIGNET Pierre's avatar
VIGNET Pierre committed
38 39 40 41 42 43 44 45
##
## Contributor(s): Geoffroy Andrieux, Nolwenn Le Meur
##
"""
Controller and auxiliary widgets for simulations with gui.
"""
import gtk
from time import clock
46
import pkg_resources
VIGNET Pierre's avatar
VIGNET Pierre committed
47 48

from chart_chrono import ChartChrono
49
from cadbiom_gui.gt_gui.utils.warn import cancel_warn
50
from cadbiom.models.guard_transitions.simulator.simul_exceptions import \
VIGNET Pierre's avatar
VIGNET Pierre committed
51
                              SimulException, SimulStopException
52 53 54
from cadbiom.models.guard_transitions.simulator.chart_simul import ChartSimulator
from cadbiom.models.guard_transitions.simulator.simul_aux import ModelExtractorVisitor
from cadbiom.models.guard_transitions.analyser.ana_visitors import FrontierVisitor
55 56 57
from cadbiom_gui.gt_gui.utils.listDisplay  import ToggleList
from cadbiom_gui.gt_gui.utils.fileHandling import FileChooser

58 59
from cadbiom import commons as cm

VIGNET Pierre's avatar
VIGNET Pierre committed
60 61 62 63 64

class ChartSimulControler(object):
    """
    Control different parameters of a simulation and display panel
    """
65
    def __init__(self, emvc, sim_option, reporter,
VIGNET Pierre's avatar
VIGNET Pierre committed
66 67 68 69 70 71 72 73
                 init_places = None, icseq=None, parent = None):
        # loading and initializing the simulator model
        self.edit_mvc = emvc
        self.model = emvc.model                    # chart model
        self.option = sim_option                   # free clock treatment option
        self.reporter = reporter                   # display error messages
        self.sim = ChartSimulator()                # simulation model
        self.__reload = True
74
        if icseq: # simulation with conditions from checker
VIGNET Pierre's avatar
VIGNET Pierre committed
75 76 77 78 79 80 81 82
            self.sim.set_act_input_stream(icseq)
            self.__reload = False
        if init_places:
            self.__reload = False
        self.sim.build(self.model, sim_option, reporter)
        if reporter.error:
            DisplayError(reporter, self.model.name)
            return
83

VIGNET Pierre's avatar
VIGNET Pierre committed
84 85 86 87
        self.init_places = init_places
        if self.init_places:
            self.sim.simul_init_places(self.init_places)
        else:
88 89
            self.sim.simul_init()

VIGNET Pierre's avatar
VIGNET Pierre committed
90 91 92 93 94 95
        self.max_step = 0
        self.tempo = 0.0
        self.stop = False
        self.selected_chrono = False
        self.main_window = None
        self.selected_window = None
96

VIGNET Pierre's avatar
VIGNET Pierre committed
97
        # graphical interface
98
        # Set the Glade
99 100 101 102 103
        template = pkg_resources.resource_filename(
            __name__,
            "../chart_glade/chart_simulator.glade"
        )
        self.wtree = gtk.glade.XML(template)
104

VIGNET Pierre's avatar
VIGNET Pierre committed
105 106 107
        # Get the Main Window, and connect the "destroy" event
        self.main_window = self.wtree.get_widget("window1")
        self.main_window.set_title("Simulation: "+self.model.name)
108 109 110
        self.main_window.connect("destroy", self.on_destroy)
        # Event on_escape key pressed
        self.main_window.connect("key_press_event", self.on_escape)
VIGNET Pierre's avatar
VIGNET Pierre committed
111 112
        self.main_window.set_position(gtk.WIN_POS_CENTER)
        self.main_window.set_keep_above(True)
113 114 115 116 117 118
        # Favicon
        favicon = pkg_resources.resource_filename(
            __name__,
            "../images/favicon.ico"
        )
        self.main_window.set_icon_from_file(favicon)
119

VIGNET Pierre's avatar
VIGNET Pierre committed
120 121 122 123 124
        # frontier button (disconnected when icseq are computed)
        button = self.wtree.get_widget("frontier_button")
        button.connect("clicked", self.on_select_front)
        if icseq:
            button.set_sensitive(False)
125

VIGNET Pierre's avatar
VIGNET Pierre committed
126 127 128 129 130
        # whole button (disconnected when ic are computed)
        button = self.wtree.get_widget("whole_button")
        button.connect("clicked", self.on_select_whole)
        if icseq:
            button.set_sensitive(False)
131

VIGNET Pierre's avatar
VIGNET Pierre committed
132 133 134
        # start button
        button = self.wtree.get_widget("startbutton")
        button.connect("clicked", self.on_start)
135

VIGNET Pierre's avatar
VIGNET Pierre committed
136 137 138
        # chrono nutton
        button = self.wtree.get_widget("chronobutton")
        button.connect("clicked", self.on_chrono)
139

VIGNET Pierre's avatar
VIGNET Pierre committed
140
        # input file choser (disconnected when ic are computed)
141
        input_file_button = self.wtree.get_widget("input_file_button")
VIGNET Pierre's avatar
VIGNET Pierre committed
142
        if not self.sim.has_input():
143 144
            input_file_button.set_sensitive(False)
        input_file_button.connect("clicked", self.on_input_file_selected)
VIGNET Pierre's avatar
VIGNET Pierre committed
145
        if icseq:
146
            input_file_button.set_sensitive(False)
147

VIGNET Pierre's avatar
VIGNET Pierre committed
148 149 150
        # step button
        button = self.wtree.get_widget("stepbutton")
        button.connect("clicked", self.on_step_simul)
151

VIGNET Pierre's avatar
VIGNET Pierre committed
152 153 154

        # check button for chronogram
        self.cb_chrono = self.wtree.get_widget("cb_chrono")
155

VIGNET Pierre's avatar
VIGNET Pierre committed
156 157
        # nb of steps widget
        self.nb_step_entry = self.wtree.get_widget("nbsteps")
158

VIGNET Pierre's avatar
VIGNET Pierre committed
159 160 161 162
        # slider
        self.range = self.wtree.get_widget("hscale1")
        self.range.set_update_policy(gtk.UPDATE_DISCONTINUOUS)
        self.range.connect("value_changed", self.on_delay)
163

VIGNET Pierre's avatar
VIGNET Pierre committed
164 165 166
        # init button"
        button = self.wtree.get_widget("initbutton")
        button.connect("clicked", self.on_init)
167

VIGNET Pierre's avatar
VIGNET Pierre committed
168 169 170 171 172
        # reload button (disconnected when using computed input clocks)
        button = self.wtree.get_widget("reloadbutton")
        button.connect("clicked", self.on_reload)
        if not self.__reload:
            button.set_sensitive(False)
173

VIGNET Pierre's avatar
VIGNET Pierre committed
174 175 176 177
        # extract button
        button = self.wtree.get_widget("extractbutton1")
        button.connect("clicked", self.on_extract, False)
        button = self.wtree.get_widget("extractbutton2")
178 179
        button.connect("clicked", self.on_extract, True)

180 181 182 183 184 185
        # Tooltips
        self.tooltips = gtk.Tooltips()
        self.tooltips.set_tip(input_file_button, "Load one solution from a file")
        self.tooltips.enable()
        self.tooltips.set_delay(cm.TOOLTIPS_DELAY)

VIGNET Pierre's avatar
VIGNET Pierre committed
186 187 188 189 190 191 192 193 194 195
        # register itself for parent or emvc
        if parent:
            parent.win_register(self)
        else:
            self.edit_mvc.win_register(self)
        self.parent = parent

        # display
        self.main_window.show_all()
        #gtk.main()
196

VIGNET Pierre's avatar
VIGNET Pierre committed
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
    def on_destroy(self, widget):
        """
        destroy the windows after all secondary windows
        """
        if self.selected_window:
            self.selected_window.destroy()
        if self.sim.chrono:
            self.sim.chrono.window.destroy()
        self.model.clean()
        self.model.notify()
        if self.parent:
            self.parent.win_remove(self)
        else:
            self.edit_mvc.win_remove(self)
        if self.main_window:
            self.main_window.destroy()
213

VIGNET Pierre's avatar
VIGNET Pierre committed
214 215 216 217 218
    def destroy(self):
        """
        Used if chart_simul_controller is itself a secondary window
        """
        self.on_destroy(None)
219

220 221 222 223 224
    def on_escape(self, widget, event):
        """On ESC key_press_event, destroy this window."""
        if gtk.gdk.keyval_name(event.keyval) == "Escape":
            self.destroy()

VIGNET Pierre's avatar
VIGNET Pierre committed
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
    def on_step_simul(self, widget):
        """
        callback for step by step simulation
        """
        # in case a selected chrono is open"
        if self.selected_chrono:
            self.sim.chrono.destroy()
            self.sim.chrono = None
            self.selected_chrono = False
        if self.sim.has_input() and not self.sim.input_buffer:
            # inputs present and no input file
            cancel_warn("Set input file before simulation")
            return
        try:
            self.sim.simul_step()
            if self.sim.chrono:
                self.sim.chrono.register(self.sim)
                self.sim.chrono.update()
        except SimulStopException:
            cancel_warn("Simulation reached end of input")
245
        except SimulException as exc:
VIGNET Pierre's avatar
VIGNET Pierre committed
246
            cancel_warn("Problem in simulation: " + exc.__str__())
247 248


VIGNET Pierre's avatar
VIGNET Pierre committed
249
    def on_input_file_selected(self, widget):
250
        """Choose an input file"""
251
        fch = FileChooser("Input file", "", "*", save_window=False)
VIGNET Pierre's avatar
VIGNET Pierre committed
252
        fch.do_action(self.set_input_file)
253

VIGNET Pierre's avatar
VIGNET Pierre committed
254
    def set_input_file(self, filename):
255 256 257 258 259 260
        """Open an input file

        Test first line of the input file
        => must begin with one of these words:
        "$inputs" or "%", or any word (full scenario, where the first line
        is a set of place names)
VIGNET Pierre's avatar
VIGNET Pierre committed
261 262
        """
        inputfile = open(filename, 'r')
263
        line_split = inputfile.readline().split()
VIGNET Pierre's avatar
VIGNET Pierre committed
264 265 266 267 268
        inputfile.close()
        # test type of file on first line
        if line_split[0] == "$inputs": # old coded input
            try:
                self.sim.set_cfile_input_stream(filename)
269
            except Exception as exc:
270
                cancel_warn("Error in coded input file loading" + str(exc))
VIGNET Pierre's avatar
VIGNET Pierre committed
271 272 273 274
            return
        elif  line_split[0] == "%": # activated input
            try:
                self.sim.set_act_file_input_stream(filename)
275
            except Exception as exc:
276
                cancel_warn("Error in active input file loading" + str(exc))
VIGNET Pierre's avatar
VIGNET Pierre committed
277
            return
278 279
        else:
            # assume correct scenario
VIGNET Pierre's avatar
VIGNET Pierre committed
280 281
            try:
                self.sim.set_sce_file_input_stream(filename)
282
            except Exception as exc:
283
                cancel_warn("Error in scenario loading" + str(exc))
284
            return
VIGNET Pierre's avatar
VIGNET Pierre committed
285 286 287 288 289 290 291 292 293 294


    def on_init(self, widget):
        """
        initialisation of the simulator
        """
        if self.sim.init_places:
            self.sim.simul_init_places(self.sim.init_places)
        else:
            self.sim.simul_init() # standard init from graphics
295

VIGNET Pierre's avatar
VIGNET Pierre committed
296 297 298 299 300 301 302 303 304 305 306
        if self.sim.input_buffer:
            self.sim.input_buffer.rewind()
        if self.sim.chrono:
            if self.selected_chrono:
                self.sim.chrono.window.destroy()
                self.sim.chrono = None
                self.selected_chrono = False
            else:
                self.sim.chrono.rewind()
                self.sim.chrono.register(self.sim)
                self.sim.chrono.update()
307

VIGNET Pierre's avatar
VIGNET Pierre committed
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
    def on_start(self, widget):
        """
        start a simulation
        """
        # check inputs
        if self.sim.has_input() and not self.sim.input_buffer:
            # inputs present and no input file
            cancel_warn("Set input file before simulation")
            return
        # read nb of steps
        max_step = self.nb_step_entry.get_text()
        if max_step == "":
            self.max_step = 0
            cancel_warn("Set number of simulation steps")
        else:
            self.max_step = int(max_step)
        self.step_count = 0
        self.stop = False
#        a = threading.Thread(None, self.loop, None, (), None)
#        a.start()
#        return
        # selected chrono
        if self.cb_chrono.get_active():
            if self.sim.chrono:
                self.sim.chrono.destroy()
            self.sim.chrono = ChartChrono.for_trajectory(self.sim)
            self.selected_chrono = True
        self.loop()
        if self.selected_chrono:
            self.sim.chrono.display_selected_chrono()
338

VIGNET Pierre's avatar
VIGNET Pierre committed
339 340 341 342 343 344 345 346 347 348 349 350 351 352
    def loop(self):
        """
        temporized loop for automatic simulation
        """
        if self.sim.chrono:
            self.sim.chrono.register(self.sim)
        while not self.stop and self.step_count < self.max_step:
            start_time = clock()
            try:
                self.sim.simul_step()
                self.step_count = self.step_count + 1
            except SimulStopException:
                cancel_warn("Simulation reached end of input")
                return
353
            except SimulException as exc:
VIGNET Pierre's avatar
VIGNET Pierre committed
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
                cancel_warn("Problem in simulation:" + exc.__str__())
                return
            self.model.notify()
            if self.sim.chrono:
                self.sim.chrono.register(self.sim)
                self.sim.chrono.update()
            # tempo
            if self.tempo > 0.01:
                time = clock()
                delay = time - start_time
                while delay < self.tempo:
                    time = clock()
                    delay = time - start_time

    def on_chrono(self, widget):
        """
        setup chronogram
        """
        if not self.sim.chrono:
            # logical analyser
374
            self.sim.chrono = ChartChrono.from_simulation_model(self.sim)
VIGNET Pierre's avatar
VIGNET Pierre committed
375 376 377 378 379 380
            self.sim.chrono.register(self.sim)
            self.sim.chrono.update()
        else:
            self.sim.chrono.destroy()
            self.sim.chrono = None
            self.selected_chrono = False
381

VIGNET Pierre's avatar
VIGNET Pierre committed
382 383 384 385 386
    def on_delay(self, widget):
        """
        adjust the simulation timer
        """
        self.tempo = self.range.get_value()/50.0
387

VIGNET Pierre's avatar
VIGNET Pierre committed
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
    def on_reload(self, widget):
        """
        reset the simulator
        """
        if not self.__reload:
            cancel_warn("No reload allowed")
            return
        if self.sim.chrono:
            self.sim.chrono.destroy()
        input_file = self.sim.input_file
        self.sim = ChartSimulator()
        self.reporter.error = False
        self.sim.build(self.model, self.option, self.reporter)
        if self.reporter.error:
            DisplayError(self.reporter, self.model)
            return
        if input_file:
            try:
                self.set_input_file(input_file)
407
            except SimulException:
VIGNET Pierre's avatar
VIGNET Pierre committed
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
                self.sim.input_buffer = None
                cancel_warn ("old input file inadequate - redefine input")
        if self.sim.chrono:
            self.sim.chrono.destroy()
            self.sim.chrono = ChartChrono.from_simulation_model(self.sim)
        if self.init_places:
            self.sim.simul_init_places(self.init_places)
        else:
            self.sim.simul_init() # standard init from graphics
        if self.sim.chrono:
            self.sim.chrono.register(self.sim)
            self.sim.chrono.update()
        self.max_step = 0
        self.tempo = 0.0
        self.stop = False
423

VIGNET Pierre's avatar
VIGNET Pierre committed
424 425 426 427 428 429 430 431 432
    def on_extract(self, widget, ex_type):
        """
        extract the part of a model used in last simulation
        """
        if self.sim.get_step() < 2:
            return
        mex = ModelExtractorVisitor('sim_extract', ex_type)
        self.model.accept(mex)
        model = mex.sub_model
433
        self.edit_mvc.charter.add_edit_mvc(model.name, model=model, layout=False, w_destroy=False)
VIGNET Pierre's avatar
VIGNET Pierre committed
434
        self.edit_mvc.charter.do_layout(None,"hierarchical_LR")
435

VIGNET Pierre's avatar
VIGNET Pierre committed
436 437 438 439 440
    def on_select_front(self, widget):
        """
        selection of frontier activated places at initialization
        """
        self.selected_window = SelectPlaceWindow(self, True)
441

VIGNET Pierre's avatar
VIGNET Pierre committed
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
    def on_select_whole(self, widget):
        """
        selection of activated places at initialization
        """
        self.selected_window = SelectPlaceWindow(self, False)




class DisplayError(object):
    """
    auxiliary widget for simulator
    """
    def __init__(self, report, model_name, text=None):
        self.main_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        #self.main_window.connect("destroy", gtk.main_quit)
        self.main_window.set_title("Compiler errors or info: " + model_name)
        self.main_window.set_position(gtk.WIN_POS_CENTER)
        self.main_window.set_keep_above(True)
461
        self.main_window.set_default_size(500, 300)
462

VIGNET Pierre's avatar
VIGNET Pierre committed
463 464 465 466
        scroll = gtk.ScrolledWindow()
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        scroll.set_shadow_type(gtk.SHADOW_IN)
        self.main_window.add(scroll)
467

VIGNET Pierre's avatar
VIGNET Pierre committed
468 469 470 471 472 473 474 475
        write = gtk.TextView()
        if report:
            write.get_buffer().set_text(report.memory)
        else:
            write.get_buffer().set_text(text)
        scroll.add_with_viewport(write)
        self.main_window.show_all()
        #gtk.main()
476

VIGNET Pierre's avatar
VIGNET Pierre committed
477 478 479 480 481
class SelectPlaceWindow(object):
    """
    Select the activated place for initialization
    """
    def __init__(self,  simulator, frontier_bool):
482

VIGNET Pierre's avatar
VIGNET Pierre committed
483 484 485
        self.simulator = simulator
        # graphical interface
        # Set the Glade file
486 487 488 489 490
        template = pkg_resources.resource_filename(
            __name__,
            "../chart_glade/simu_places.glade"
        )
        self.wtree = gtk.glade.XML(template)
491

VIGNET Pierre's avatar
VIGNET Pierre committed
492 493 494 495 496 497
        # Get the Main Window, and connect the "destroy" event
        self.window = self.wtree.get_widget("window1")
        self.window.set_title("Selected window")
        self.window.set_size_request(250, 400)
        self.window.set_position(gtk.WIN_POS_NONE)
        self.window.set_keep_above(True)
498

VIGNET Pierre's avatar
VIGNET Pierre committed
499 500 501
        place_notebook = self.wtree.get_widget("place_notebook")
        # search
        if frontier_bool:
502
            self.search_area = ToggleFrontier(self.simulator.model,
503
                                              place_notebook, "Frontier nodes")
VIGNET Pierre's avatar
VIGNET Pierre committed
504
        else:
505 506
            self.search_area = ToggleWholeModel(self.simulator.model,
                                                place_notebook,
507
                                                "Simple nodes")
VIGNET Pierre's avatar
VIGNET Pierre committed
508

509

VIGNET Pierre's avatar
VIGNET Pierre committed
510 511 512 513
        # button
        button = self.wtree.get_widget("select_button")
        button.connect("clicked", self.on_select)
        button = self.wtree.get_widget("unselect_button")
514
        button.connect("clicked", self.on_deselect)
VIGNET Pierre's avatar
VIGNET Pierre committed
515 516 517 518 519 520
        button = self.wtree.get_widget("save_button")
        button.connect("clicked", self.on_save)
        button = self.wtree.get_widget("load_button")
        button.connect("clicked", self.on_load)
        button = self.wtree.get_widget("validate_button")
        button.connect("clicked", self.on_validate)
521

VIGNET Pierre's avatar
VIGNET Pierre committed
522 523
        # display
        self.window.show_all()
524

VIGNET Pierre's avatar
VIGNET Pierre committed
525 526 527 528 529

    def destroy(self):
        """
        as usual for aux widget
        """
530 531
        self.window.destroy()

VIGNET Pierre's avatar
VIGNET Pierre committed
532 533 534 535
    def on_select(self, widget):
        """
        ???
        """
536
        self.search_area.sn_viewer.select_all()
537

538
    def on_deselect(self, widget):
VIGNET Pierre's avatar
VIGNET Pierre committed
539 540 541
        """
        ???
        """
542
        self.search_area.sn_viewer.deselect_all()
543

VIGNET Pierre's avatar
VIGNET Pierre committed
544 545 546 547
    def on_save(self, widget):
        """
        open a window to save initialization
        """
548
        choice = gtk.FileChooserDialog("Save initialization", None,
VIGNET Pierre's avatar
VIGNET Pierre committed
549 550 551 552
                                       gtk.FILE_CHOOSER_ACTION_SAVE,
                                       (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                        gtk.STOCK_SAVE, gtk.RESPONSE_OK))
        choice.set_default_response(gtk.RESPONSE_OK)
553

VIGNET Pierre's avatar
VIGNET Pierre committed
554 555 556 557 558
        #add a filter to see only txt files
        filter = gtk.FileFilter()
        filter.set_name("text files")
        filter.add_pattern("*.txt")
        choice.add_filter(filter)
559

VIGNET Pierre's avatar
VIGNET Pierre committed
560 561 562 563 564
        #add a filter to see all
        no_filter = gtk.FileFilter()
        no_filter.set_name("all")
        no_filter.add_pattern("*")
        choice.add_filter(no_filter)
565

VIGNET Pierre's avatar
VIGNET Pierre committed
566 567 568 569 570 571 572
        response = choice.run()
        if response == gtk.RESPONSE_OK:
            self.create_init_file(choice.get_filename())
        elif response == gtk.RESPONSE_CANCEL:
            pass
            #print 'Closed, no files selected'
        choice.destroy()
573

VIGNET Pierre's avatar
VIGNET Pierre committed
574 575 576 577
    def on_load(self, widget):
        """
        open a window to search xml file coming from PID database
        """
578
        choice = gtk.FileChooserDialog("Import from xml", None,
VIGNET Pierre's avatar
VIGNET Pierre committed
579 580 581 582
                                       gtk.FILE_CHOOSER_ACTION_OPEN,
                                       (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                        gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        choice.set_default_response(gtk.RESPONSE_OK)
583

VIGNET Pierre's avatar
VIGNET Pierre committed
584 585 586 587 588
        #add a filter to see only xml files
        filter = gtk.FileFilter()
        filter.set_name("text files")
        filter.add_pattern("*.txt")
        choice.add_filter(filter)
589

VIGNET Pierre's avatar
VIGNET Pierre committed
590 591 592 593 594
        #add a filter to see all
        no_filter = gtk.FileFilter()
        no_filter.set_name("all")
        no_filter.add_pattern("*")
        choice.add_filter(no_filter)
595

VIGNET Pierre's avatar
VIGNET Pierre committed
596 597 598 599 600 601 602
        response = choice.run()
        if response == gtk.RESPONSE_OK:
            self.load_init_file(choice.get_filename())
        elif response == gtk.RESPONSE_CANCEL:
            #print 'Closed, no files selected'
            pass
        choice.destroy()
603

VIGNET Pierre's avatar
VIGNET Pierre committed
604 605 606 607 608 609 610 611 612 613 614 615
    def on_validate(self, widget):
        """
        validate the choice of activated places
        """
        self.set_places()
        self.destroy()

    def create_init_file(self, file_name):
        """
        make a txt file with the current selected places
        """
        file = open(file_name,'w')
616
        list_of_places = self.search_area.get_selected_items()
VIGNET Pierre's avatar
VIGNET Pierre committed
617
        for place in list_of_places :
618
            file.write(str(place)+'\n')
VIGNET Pierre's avatar
VIGNET Pierre committed
619 620
        file.close()
        return
621

VIGNET Pierre's avatar
VIGNET Pierre committed
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
    def load_init_file(self, file_name):
        """
        load a file to initialize the simulator
        """
        list_of_places = []
        file = open(file_name,'r')
        for line in file:
            name = line[:-1]
            if name not in self.search_area.list_nodes :
                cancel_warn("Name in the file not in the model")
                return
            list_of_places.append(name)
        self.search_area.sn_viewer.set_selected_items(list_of_places)
#        self.simulator.sim.simul_init_places(list_of_places)
#        self.destroy()

    def set_places(self):
        """
        set the chosen activated places
        """
642 643
        self.simulator.init_places = self.search_area.get_selected_items()
        skw = list(self.simulator.init_places)
VIGNET Pierre's avatar
VIGNET Pierre committed
644 645 646 647 648 649 650 651 652 653
        self.simulator.sim.simul_init_places(skw)

class ToggleWholeModel(object):
    """
    List of simple nodes for searching
    """
    def __init__(self, model, notebook, label):
        self.model = model
        self.model_changed = True
        self.notebook = notebook
654

VIGNET Pierre's avatar
VIGNET Pierre committed
655 656 657 658 659 660 661 662 663 664 665
        # simple nodes
        sn_frame = gtk.Frame()
        vbox = gtk.VBox(False, 0)
        sn_frame.add(vbox)
        # simple nodes list
        self.sn_viewer = ToggleList()
        label = gtk.Label(label)
        # wrap into scrollwindow
        scroll = gtk.ScrolledWindow()
        scroll.add_with_viewport(self.sn_viewer)
        vbox.pack_start(scroll, True, True, 0)
666

VIGNET Pierre's avatar
VIGNET Pierre committed
667
        notebook.append_page(sn_frame, label)
668

VIGNET Pierre's avatar
VIGNET Pierre committed
669 670 671 672 673 674
        # get node names
        lnode = model.get_simple_node_names()
        lnode.sort()
        self.list_nodes = lnode
        # display node names
        self.sn_viewer.refresh(lnode)
675

676
    def get_selected_items(self):
VIGNET Pierre's avatar
VIGNET Pierre committed
677 678 679 680
        """
        retrieve the selected items
        """
        return self.sn_viewer.get_selected_items()
681

VIGNET Pierre's avatar
VIGNET Pierre committed
682 683 684 685 686 687
class ToggleFrontier(ToggleWholeModel):
    """
    List of frontier nodes for searching
    """
    def __init__(self, model, notebook, label):
        ToggleWholeModel.__init__(self, model, notebook, label)
688

VIGNET Pierre's avatar
VIGNET Pierre committed
689 690 691 692 693 694
        self.model = model
        # get node names
        lnode = self.get_frontier_node_names()
        lnode.sort()
        self.list_nodes = lnode
        # display node names
695 696
        self.sn_viewer.refresh(lnode)

VIGNET Pierre's avatar
VIGNET Pierre committed
697 698 699 700 701 702
    def get_frontier_node_names(self):
        """
        retrieve frontier nodes from the model
        """
        fvi = FrontierVisitor()
        self.model.accept(fvi)
703
        return fvi.frontier