SwingGui updates... Search For Service - cuz time is precious :)

We want to find our service quick !  So many services now, who has time to scroll ?
Now in the SwingGui - Search !  (honestly should have done this years ago ;)


Servo Joystick & Arduino seem to work over a remote connection now (mostly) - BoardInfo & DeviceSummary were not serializable (fixed)

There are still a few issues regarding displaying of ports and some other thing - most can be fixed by using asynchronous messaging in the SwingGuis.  If you use the Service directly (except in onState) it will probably cause problems ...

Oh .. and don't create a service when they are connected - interesting endlless service tabs are created 


Original Joystick was worky - but only for specific models of joystick which had hardcoded component names.  Then Joystick Gui was borked . Now ! Joystick Gui is dynamically built based on what it finds in the components - it can inspect and attempt to interface with anything jinput can find.


 

There are lots of updates to the SwingGui although some of them are not evidently noticible.  On is that messaging in the SwingGui is closer now in design to the routing of messages and callbacks in the WebGui

On advantage of this is the ability now to create "Widgets".  Swing Widgets are simple objects which allow you to "view" some aspect of a service through the tab UI of another service.  Take Serial for example.  "Everything" needs the serial service, so its nice to be able to "view" the controls of connect/disconnect, port selection, and refreshing ports through the Service your using (e.g. like Arduino)

This 'sort-of' worked before, but it was a mess, each service copy/pasted parts of the SerialGui into there own.  Some worked .. some did not.  But Now !!  There's just a single PortGui !!!

And it always behaves the same, and it works !  And its as simple as this:

portGui = new PortGui(serial.getName(), myService, tabs);
addTop(3, portGui.getDisplay());

That's it .. 2 lines - make it & display it...  it takes care of everything else ...

 

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...

Mats's picture

Joystick GUI

Hi GroG

Nice work on the Joystick service.

I tested to connect a PS3 joystick to my Raspberry PI3 that has built in Bluetooth.

I used this guide: https://www.piborg.org/blog/pi-zero-wifi-ps3.

It worked fine. I can see the joystick as /dev/input/js0

When I run test program jstest I get a lot of values that change when I use the joystick.

So from a hardware and OS perspective it works.

I also used this guide to install jinput and jni on the PI.

http://stackoverflow.com/questions/20851911/jinput-on-raspberrypi

But it doesn't work whe I try to use the Joystick service from MRL. The dropdown list of controllers is empty.

I guess that MRL doesn't find the neccessary jinput / jni libraries.

Any ideas ?

 

Mats's picture

Joystick service on Raspberry PI3

Hi

I can see that when I install the Joystick service on the PI3 it retreives armv7.hfp.32.linux

If I look on what's available in the repo in Eclipse, I find armv6.hfp.32.linux, but no armv7.hfp.32.linux 

I think the difference between arm6 and arm7 is the problem.

When I install the Joystick in Windows the native libraries gets unzipped, but not on the PI.

Not sure about the best way to make it worky.

If the binaries are compatible between arm6 and arm7 perhaps it's ok to use the arm6 binaries, otherwise they need to be compiled for arm7.

I also tested on a PI2, and it also tries to retreive armv7.hfp.32.linux

I Googled a little more and arm6 and arm7 code both work on Pi2 and Pi3. 

So the best alternative would be to make the Joystick service on the PI detect and unpack the arm6 binaries.

But I'm not sure about how the os detection mechanism for the repo works.

Looking more into the repo I think that some minor changes to the repo should do the trick.

I copied /repo/net.java.games.jinput/20120914/armv6.hfp.32.linux.zip to /repo/net.java.games.jinput/20120914/armv7.hfp.32.linux.zip
 
And then I added a line in the ixy.xml to use the copied zip.file.
 
And tested. Now it's worky :)