GUIService is now Swing ! - with no more freezing !

Good News .. All compilation errors are fixed, I've gone through "some" Swing user interfaces and fixed them up (using the new ServiceGui helper methods .. e.g. addLine etc.)
OH .. AND I FIXED THE YEAR OLD BUG OF THE GUI FREEZING ON STARTUP !!! - also lots and lots of clean up.

Bad News ... GUIService is NO LONGER GUIService .. Service names should be implementation specific.  hence for this day forward GUIService will now be "Swing" .. I've fixed and synced everything I could on "develop" branch - including all scripts in Pyrobotlab (develop branch) ..   This is also in preperation for JavaFX as it is the next "Swing" for native windows Java UIs.

Please let me know if you run into any problems - thanks ..

MQTT Gui .. 
Now it worky  !  There was much refactoring and a bit of learning Mqtt ...  

Its fun to send messages to a Mqtt broker .. but its funner to connect MRL instances through it  !
(That will be step 2) :)

 

Categories are Worky ! (again)

 

I've been having fun refactoring the Swing GUIService.  I've learned a considerable amount about user interfaces, Swing, MVC and a bit about JavaFX since I started the GUIService a gazillion years ago.  In the process of cleaning up all the sins I committed in the past (ie spaghetti code) I've been re-writing service guis and testing them.  

When I started updating KeyboardGui I cam across Mat's added gem.  He Borg'd in jnativehook project - which puts a global hook into keyboard & mouse.  I moved it from the KeyboardGui into the service.  It publishes keyboard and mouse events if MRL loses focus, or even if there is no gui at all !  Thanks Mats !

I've made ui helper methods in the ServiceGui (parent class to all Swing service panels) - and it can produce the keyboard ui with only 4 lines of code.  Adding more stuff is as simple as adding more panels or lines of variables or labels.   

public KeyboardGui(final String boundServiceName, final GUIService myService, final JTabbedPane tabs) {
    super(boundServiceName, myService, tabs);
    addPanel("keyboard");
    addLine("key", lastKey, "code", lastKeyCode);
    addPanel("mouse");
    addLine(mouseX, ",", mouseY);
  }

There is no longer any init() .. all gui construction is done in the service gui's constructor.  The init() was residual from Applet programming.

getState(Service service)  has been changed to onState(Service service) 

public void onState(Keyboard keyboard) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
      }
    });
  }

This goes with the rule where :

         publish{Method}  ---will call --> on{Method}  or
         get{Method}  ---will call --> on{Method}

The publishState --> onState is auto-magicaly subscribe to by the framework - so is publishStatus.  The keyboard service doesn't need the onState event handler - as most of the data flows through specific subscribes and the whole service doesnt need to be sent in these situations.
 
Now only "special" subscribes are needed, and they can be put into subscribeGui and unsubscribeGui sections.  These setup all the intersting callbacks, or remove them when the service is released
@Override
  public void subscribeGui() {
    subscribe("publishKey");
    subscribe("publishKeyCode");
    subscribe("publishMouseMoved");
  }

  @Override
  public void unsubscribeGui() {
    unsubscribe("publishKey");
    unsubscribe("publishKeyCode");
    unsubscribe("publishMouseMoved");
  }

Not sure how long it will take me .. but with the new structure and helper methods - the code is substantially smaller and cleaner...

Still have more work before I check in ...  back to the polishing !

 

 


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Mats's picture

GUI refactoring

That's really nice. When I created GUI's for the i2c devices, I tested by building both the Swing and theWeb gui in parallell to make sure that they were in sync.

I tried to conform to the idea that the GUI should only talk to it's own service, and not to other services.

In some cases it makes the service code a little larger, but it gives the advantage that the GUI's ( Swing and Web ) can use the same methods.

One example that you will find in all i2c services  ( not the GUI ) is that I subscribe to onRegistered to be able to populatethe list of services that can be used in the GUI for a specific interface. Then the GUI's use that list to populate the dropdown list.

So in the WebGui it's easy to just do a data binding and that's also what I do in the Swing Gui. You can see how little code there is in the GUI's for i2c devices. And it can probably be cleaned up even more.

So using the same design principles in the Swing GUI as are used in Webgui / angular.js makes the GUI code small.

 

GroG's picture

Thanks Mats, Yes we like

Thanks Mats,

Yes we like small easy to read code ! 

You made a couple great points, and I think its a brilliant idea to work on both guis at once ..  Doing so when even adjusting the framework will make them more similar and easier to implement what we want in less time.

I still have a lot of framework updates to the swing ui, but I will do my best to try to keep the 2 in sync.

One of the things is the swing ui auto-matically creates onState & onStatus subscriptions.. but the onRegistered & onReleased could/should be auto-matically subscribed to as well.

I've been working on getting categories fixed again .. and they are working.
In the past this was just a static xml file, then a static json file, now its incorporated in the class getMetaData.. but I now understand where this is headed...

Categories are pretty much the same as the "interesting" interfaces of the services !  
Speech is 'effectively' the SpeechSynthesis Interface !! ..  You can switch things of the same category/interface.  That was always the intention of the design !

So next refactoring .. in the future we would not have categories - but the categories would be extracted from the interfaces...