Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » WindowBuilder » Integrate referenceSize of PicturePanel (with ScalablePictureLayout if NOT Beans.isDesignTime())
Integrate referenceSize of PicturePanel (with ScalablePictureLayout if NOT Beans.isDesignTime()) [message #848930] Wed, 18 April 2012 18:11
A0 H is currently offline A0 HFriend
Messages: 1
Registered: April 2012
Junior Member
Hello window builder experts!

BEGIN "SITUATION DESCRIPTION"
Last week I implemented a PicturePanel derived from JPanel. PicturePanel overrides method paintComponent and draws a (typically large) image fitting to the current size of the PicturePanel. The larger the PicturePanel gets the larger the image is scaled.

Likewise to a JPanel, on the PicturePanel any components can be placed and any LayoutManager (FlowLayout, BorderLayout, ...) can be used to layout the components bounds.
If AbsoluteLayout (setLayout(null)) is chosen, I have implemented some special behaviour. In DesignTime if an AbsoluteLayout is chosen, the PicturePanel behaves same as a JPanel. But if the PicturePanel with AbsoluteLayout is used in productive environment (NOT Beans.isDesignTime()), the locations of the components placed on the PicturePanel get scaled according to current size of the PicturePanel. The larger the width of the PicturePanel is, the larger are the x-coordinates of the components placed on it.

Technically I have achieved this by replacing the the layout manager from null to ScalablePictureLayout, if the configured LayoutManager is null (AbsoluteLayout) AND if the PicturePanel is in productive environment (NOT Beans.isDesignTime()).
The ScalablePictureLayout caches on the first execution of method layoutContainer the original locations of all components placed on the PicturePanel into a HashMap<Component, Point>. On each execution of the method layoutContainer the locations of the components are scaled according to the current size of the PicturePanel (pseudo-code: usingComponentX = originalComponentX * currentPicturePanelWidth / referencePicturePanelWidth, usingComponentY = originalComponentY * currentPicturePanelHeight / referencePicturePanelHeight).
But now you might wonder, where is the referencePicturePanelWidth and referencePicturePanelHeight from.
Since the PicturePanel is (regularly) layout managed (e.g. the PicturePanel is contained by a JPanel with a BorderLayout and the PicturePanel is assigned the layout constraint BorderLayout.CENTER), in designTime no size or bounds are stored for the PicturePanel and all parent panels. In order to make the ScalablePictureLayout calculation possible, I had to add a referenceSize (type Dimension) property to the PicturePanel. The value of the referenceSize in the PicturePanel is accessed from the ScalablePictureLayout every time when the method layoutContainer is being executed.

I have completely implemented the PicturePanel and the ScalablePictureLayout and both work fine. The PicturePanel is integrated into windowbuilder. (The ScalablePictureLayout is not present in the window builder since it is only used in productive environment - as explained above.)
END "SITUATION DESCRIPTION"

BEGIN "PROBLEM DESCRIPTION"
Currently the PicturePanel is not perfectly configurable in design time within window builder.

For the PicturePanel the window builder user (panel designer) has to set the referenceSize correctly. He has to type the same size into the property referenceSize as the current size (within window builder) of the PicturePanel is. If the referenceSize is not set correctly, the layout calculation in ScalablePictureLayout does not work as desired.
END "PROBLEM DESCRIPTION"

BEGIN "SOLUTION REQUIRED"
We want, that the referenceSize in the PicturePanel is updated automatically, when the user changes (indirectly) the size of the PicturePanel. (A size change can occur, e.g. when the user adjusts the layout constraint of the PicturePanel or a parent panel, e.g. when the user selects another layout manager for a parent Panel, e.g. when the user changes the size of a parent panel with AbsoluteLayout, or e.g. when user changes the current viewing size (not stored in the generated java code) of the outermost root panel (if it has a layout manager assigned).)

I haven't found any approach compliant to the java beans standard. Since our customers only use window builder (a customized version of it with small additional plugins), it is (ignoring the effort, know-how and maintenance aspects) absolutely no problem, if we implement the update of the reference size directly in window builder.

My currently best idea (implementing it directly in window builder) is as following (NOT TRIED):
/* You cannot use links until you have posted more than 25 Messages */
http@dev.eclipse.org/svnroot/tools/org.eclipse.windowbuilder/trunk/org.eclipse.wb.swing/src/
org/eclipse/wb/internal/swing/model/component/ComponentInfo.java
ComponentInfo.java
In method ComponentInfo.refresh_fetch I would like to update the referenceSize after following lines:
// remember bounds
model.setBounds(CoordinateUtils.get(bounds));

Since this code is visited, when the size of a component (also when the size of the PicturePanel) has been changed (and the layout has been calculated), the new bounds can be also used to update the reference size property.

Since I have never seen window builder code before, I currently don't know what's the best way to update the reference size (including marking the panel as being changed and therefore marked with an * in the title of the editor window).

It might work, if I try to copy something of the code from GenericPropertyImpl.setExpression to the method ComponentInfo.refresh_fetch in order to update the referenceSize property (I think this way the new value would be correctly written into the abstract syntax tree.).
http@dev.eclipse.org/svnroot/tools/org.eclipse.windowbuilder/trunk/org.eclipse.wb.core.xml/src/
org/eclipse/wb/internal/core/xml/model/property/GenericPropertyImpl.java
GenericPropertyImpl.java

@Override
  public void setExpression(String expression, Object value) throws Exception {
    // validate expression
    {
      String[] expressionToValidate = new String[]{expression};
      Object[] valueToValidate = new Object[]{value};
      boolean[] validationStatus = new boolean[]{true};
      m_object.getBroadcast(GenericPropertySetExpression.class).invoke(
          this,
          expressionToValidate,
          valueToValidate,
          validationStatus);
      if (!validationStatus[0]) {
        return;
      }
      expression = expressionToValidate[0];
      value = valueToValidate[0];
    }
    // set expression
    if (value != UNKNOWN_VALUE
        && !hasTrueTag("x-keepDefault")
        && ObjectUtils.equals(value, getDefaultValue())) {
      expression = null;
    }
    setExpression0(expression);
  }


By the way, I think it won't work, if I access the setter of the property directly by using reflection as for example the method AbsoluteLayoutInfo.command_BOUNDS0 does. (I'm currently convinced, that I don't want to do it that way.)
http@dev.eclipse.org/svnroot/tools/org.eclipse.windowbuilder/trunk/org.eclipse.wb.swing/src/
org/eclipse/wb/internal/swing/model/layout/absolute/AbsoluteLayoutInfo.java
AbsoluteLayoutInfo.java
example code:
      // setSize(new java.awt.Dimension)
      {
        MethodInvocation mi = component.getMethodInvocation("setSize(java.awt.Dimension)");
        if (mi != null) {
          setSizeFound = true;
          Expression exp = (Expression) mi.arguments().get(0);
          String newCode = "new java.awt.Dimension(";
          newCode += size.width + ", " + size.height + ")";
          editor.replaceExpression(exp, newCode);
        }
      }


Could you please help me.
[requires extension point: Can you think of better Solutions (less effort or better implementation quality).]
[requires extension point: Could you please help me updating the reference size in the method ComponentInfo.refresh_fetch (Which statements do I have to use exactly?).]
[requires extension point: Could you please give me some hints how I could easily override/exchange the modified classes (From my current perspective I would prefer a new plugin, which overrides only the modified classes.).]
FORUM POST UPDATE: CURRENTLY WE HAVE DECIDED, THAT WE WANT TO EXTEND THE BEHAVIOUR OF WINDOW BUILDER ONLY WITH AN EXTENSION POINT, BECAUSE WE DON'T WANT TO RELY ON THE (CURRENT) IMPLEMENTATION OF WINDOWBUILDER (AVOID PROBLEMS WHEN UPDATING TO A NEWER VERSION OF WINDOW BUILDER).
I am just making a guess. Possibly one of these extension points could help:
???
Org.eclipse.wb.core.propertyConverters
Org.eclipse.wb.core.propertyEditors
Org.eclipse.wb.core.xml.propertyConverters
Org.eclipse.wb.core.xml.propertyEditors
Org.eclipse.wb.core.editPartConfigurators
Org.eclipse.wb.core.editPolicyFactories
Org.eclipse.wb.core.invocationEvaluatorInterceptors
...
???
The currently desired extension point would provide an extension of method ComponentInfo.refresh_fetch (as described above). Does such an extension point exist?

An alternative would be an extension point, which realizes a property editor (or something similar) for the refenceSize property. The special property editor would monitor the size changes of the PicturePanel and automatically update the referenceSize value on each change (including marking the panel editor as changed).

Is there any (extensive) documentation of the extension points. Lots of extension points have no description attached. And if, the extension point description is very concise.

Could you please help me finding an appropriate extension point and implementing it.
END "SOLUTION REQUIRED"

BEGIN "INSUFFICIENT ALTERNATIVE APPROACH"
We could implement a special property editor (with Dialog - supportsCustomEditor true) for the referenceSize. When the property editor gets opened, it retrieves the current size from the bean PicturePanel (injected into the property editor with method setSource). The property editor dialog proposes this size value to be stored in the property referenceSize. If the user clicks OK, the current size of the PicturePanel is saved as referenceSize.
We don't like this approach, since from the window builder users perspective (they aren't software developers) it is not easy to understand and is cumbersome to open this property editor.
END "INSUFFICIENT ALTERNATIVE APPROACH"

BEGIN "APPENDIX"
We have decided to use AbsoluteLayout, because the placement (with the mouse) of the components is perfectly supported when using an AbsoluteLayout. (We have also tried to implement a ScalableSpringLayout (based on SpringLayout), but sometimes the components inside the panel are accidently attached to other components instead of the parent panel - and we don't need the additional constraint features of a SpringLayout.)
We don't need a (reusable) layout manager in design time, since the ScalablePictureLayout also has to respect the width-to-height ratio of the original image (Therefore the calculation of the using locations is not as simple as shown in the illustrative pseudo-code).
Additionally we don't want to implement a new layout manager with design-time integration into window builder (which is required), because the effort would be too large.
END "APPENDIX"

King regards
a0h

[Updated on: Sat, 21 April 2012 04:54]

Report message to a moderator

Previous Topic:Loading the itens of a JComboBox from the database breaks windowbuilder
Next Topic:Component's Properties
Goto Forum:
  


Current Time: Fri Nov 28 00:43:19 GMT 2014

Powered by FUDForum. Page generated in 0.02109 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software