title: SWT Sash/SashForm mirroring
body: <p>I have tried implementing upper and lower SashForms (Children A and B) inside a horizontal SashForm (Parent). I want to be able to drag a (vertical)sash of one of the Children (child A) and have the (vertical)sash of the other child (Child B) mimic exactly the horizontal position of A.
  To do this I tried a hack creating a 'ModifiedSashForm' that exposes SashForms sashes:</p>
  
  <pre><code>public Sash[] getSashes() {
  return sashes;
  </code></pre>
  
  <p>}</p>
  
  <p>I then created a class that extends ModifiedSashForm and overrides</p>
  
  <pre><code>public void onDragSash(Event event){
  </code></pre>
  
  <p>...</p>
  
  <p>that sends a note to a listener (eg Child A) that B's sash has been dragged:
      if(sash.getParent().getData(WidgetData.DATA_DRAG_SOURCE).equals(WidgetData.DRAG_SOURCE.SOURCE)){
              fireSashDragged(event, sashIndex);
          }}</p>
  
  <p>Child A then substitutes B's sash as the event source (!):</p>
  
  <pre><code>if(sashes[sashIndex]!=null){
              event.widget=sashes[sashIndex];
          }
  
          listener.onDragSash(event);
  </code></pre>
  
  <p>and I get a somewhat functioning gui. However I get problems with the sashes getting out of sync. The code is nasty and I would rather not butcher SWT in this way.
  I then tried getting Child B's weights and pushing them into A - but again get problems - especially when sashes are dragged close to each other, the listeners weight order flips.</p>
  
  <p>Next I tried using Sash and FormLayout. Example code is below - but I still can't get the upper vertical sash to exactly mimic the movement of the lower vertical sash and vice versa.</p>
  
  <p>//Based on <a href="http://www.eclipse.org/swt/snippets/" rel="nofollow">http://www.eclipse.org/swt/snippets/</a> SWT Snippet107</p>
  
  <pre><code>public class SashTest {
  final private List&lt;Sash&gt; listeners = new ArrayList&lt;Sash&gt;();
  private Shell shell;
  
  public static void main(String[] args) {
      new SashTest().run();
  
  }
  
  void run() {
      Display display = new Display();
      final Shell shell = new Shell(display);
      shell.setText("SashTest");
      this.shell = shell;
      init();
  
      shell.pack();
      shell.open();
      while (!shell.isDisposed()) {
          if (!display.readAndDispatch())
              display.sleep();
      }
      display.dispose();
  }
  
  void init() {
  
      final FormLayout form = new FormLayout();
      shell.setLayout(form);
  
      SashForm sashForm = new SashForm(shell, SWT.VERTICAL);
      sashForm.setLayoutData(new FormData());
      Composite comp1 = new Composite(sashForm, SWT.NONE);
      comp1.setLayout(new FormLayout());
      createTopArea(comp1);
  
      Composite comp2 = new Composite(sashForm, SWT.NONE);
      comp2.setLayout(new FormLayout());
      createBottomArea(comp2);
  
  }
  
  void createTopArea(Composite comp) {
      Button button1 = new Button(comp, SWT.PUSH);
      FormData fd_button1 = new FormData();
      fd_button1.bottom = new FormAttachment(0);
      fd_button1.right = new FormAttachment(0);
      fd_button1.top = new FormAttachment(0);
      fd_button1.left = new FormAttachment(0);
      button1.setLayoutData(fd_button1);
      button1.setText("Button 1");
  
      final Sash sash = new Sash(comp, SWT.VERTICAL);
      FormData fd_sash = new FormData();
      fd_sash.bottom = new FormAttachment(0);
      fd_sash.right = new FormAttachment(0);
      fd_sash.top = new FormAttachment(0);
      fd_sash.left = new FormAttachment(0);
      sash.setLayoutData(fd_sash);
      //add the upper sash to listeners for bottom sash movement
      listeners.add(sash);
  
      Button button2 = new Button(comp, SWT.PUSH);
      FormData fd_button2 = new FormData();
      fd_button2.bottom = new FormAttachment(0);
      fd_button2.right = new FormAttachment(0);
      fd_button2.top = new FormAttachment(0);
      fd_button2.left = new FormAttachment(0);
      button2.setLayoutData(fd_button2);
      button2.setText("Button 2");
  
      FormData button1Data = new FormData();
      button1Data.left = new FormAttachment(0, 0);
      button1Data.right = new FormAttachment(sash, 0);
      button1Data.top = new FormAttachment(0, 0);
      button1Data.bottom = new FormAttachment(100, 0);
      button1.setLayoutData(button1Data);
  
      final int limit = 20, percent = 50;
      final FormData sashData = new FormData();
      sashData.left = new FormAttachment(percent, 0);
      sashData.top = new FormAttachment(0, 0);
      sashData.bottom = new FormAttachment(100, 0);
      sash.setLayoutData(sashData);
      sash.addListener(SWT.Selection, new Listener() {
          @Override
          public void handleEvent(Event e) {
              Rectangle sashRect = sash.getBounds();
              Rectangle shellRect = shell.getClientArea();
              int right = shellRect.width - sashRect.width - limit;
              e.x = Math.max(Math.min(e.x, right), limit);
              if (e.x != sashRect.x) {
                  sashData.left = new FormAttachment(0, e.x);
                  shell.layout();
                  notifyListeners(sashData);
              }
          }
      });
  
      FormData button2Data = new FormData();
      button2Data.left = new FormAttachment(sash, 0);
      button2Data.right = new FormAttachment(100, 0);
      button2Data.top = new FormAttachment(0, 0);
      button2Data.bottom = new FormAttachment(100, 0);
      button2.setLayoutData(button2Data);
  
  }
  
  void createBottomArea(Composite comp) {
      Button button3 = new Button(comp, SWT.PUSH);
      FormData fd_button1 = new FormData();
      fd_button1.bottom = new FormAttachment(0);
      fd_button1.right = new FormAttachment(0);
      fd_button1.top = new FormAttachment(0);
      fd_button1.left = new FormAttachment(0);
      button3.setLayoutData(fd_button1);
      button3.setText("Button 3");
  
      final Sash sash2 = new Sash(comp, SWT.VERTICAL);
      FormData fd_sash2 = new FormData();
      fd_sash2.bottom = new FormAttachment(0);
      fd_sash2.right = new FormAttachment(0);
      fd_sash2.top = new FormAttachment(0);
      fd_sash2.left = new FormAttachment(0);
      sash2.setLayoutData(fd_sash2);
  
      Button button4 = new Button(comp, SWT.PUSH);
      FormData fd_button2 = new FormData();
      fd_button2.bottom = new FormAttachment(0);
      fd_button2.right = new FormAttachment(0);
      fd_button2.top = new FormAttachment(0);
      fd_button2.left = new FormAttachment(0);
      button4.setLayoutData(fd_button2);
      button4.setText("Button 4");
  
      FormData button3Data = new FormData();
      button3Data.left = new FormAttachment(0, 0);
      button3Data.right = new FormAttachment(sash2, 0);
      button3Data.top = new FormAttachment(0, 0);
      button3Data.bottom = new FormAttachment(100, 0);
      button3.setLayoutData(button3Data);
  
      final int limit = 20, percent = 50;
      final FormData sashData2 = new FormData();
      sashData2.left = new FormAttachment(percent, 0);
      sashData2.top = new FormAttachment(0, 0);
      sashData2.bottom = new FormAttachment(100, 0);
      sash2.setLayoutData(sashData2);
      sash2.addListener(SWT.Selection, new Listener() {
          @Override
          public void handleEvent(Event e) {
              Rectangle sashRect = sash2.getBounds();
              Rectangle shellRect = shell.getClientArea();
              int right = shellRect.width - sashRect.width - limit;
              e.x = Math.max(Math.min(e.x, right), limit);
              if (e.x != sashRect.x) {
                  sashData2.left = new FormAttachment(0, e.x);
                  shell.layout();
              }
          }
      });
  
      FormData button4Data = new FormData();
      button4Data.left = new FormAttachment(sash2, 0);
      button4Data.right = new FormAttachment(100, 0);
      button4Data.top = new FormAttachment(0, 0);
      button4Data.bottom = new FormAttachment(100, 0);
      button4.setLayoutData(button4Data);
  
  }
  
  void notifyListeners(FormData formData){
      for(Sash sash: listeners){
          Rectangle sashRect = sash.getBounds();
  
          FormData sashData = formData;
          sash.setLayoutData(sashData);
          shell.layout();
      }
  
  }
  </code></pre>
  
  <p>}</p>
  
  <p>Do I have to write my own widget to do this or is it possible with Sash/SashForm?</p>
  
  <p>Baz, I edited your class here (too big for comments):</p>
  
  <pre><code>public class SashMirror {
  public static void main(String[] args) {
      final Display display = new Display();
      final Shell shell = new Shell(display);
      shell.setMinimumSize(new Point(200, 200));
      shell.setText("StackOverflow");
      shell.setLayout(new FillLayout(SWT.HORIZONTAL));
      final SashForm divider = new SashForm(shell, SWT.VERTICAL);
      divider.setLayout(new FillLayout(SWT.HORIZONTAL));
  
      final SashForm top = new SashForm(divider, SWT.HORIZONTAL);
      top.setLayout(new FillLayout(SWT.HORIZONTAL));
  
      final SashForm bottom = new SashForm(divider, SWT.HORIZONTAL);
      bottom.setLayout(new FillLayout(SWT.HORIZONTAL));
  
      Canvas canvasTopLeft = new Canvas(top, SWT.NONE);
      canvasTopLeft
              .setBackground(SWTResourceManager.getColor(SWT.COLOR_CYAN));
      canvasTopLeft.setLayout(new FillLayout(SWT.HORIZONTAL));
  
      Canvas canvasTopMiddle = new Canvas(top, SWT.NONE);
      canvasTopMiddle.setBackground(SWTResourceManager
              .getColor(SWT.COLOR_WHITE));
      canvasTopMiddle.setLayout(new FillLayout(SWT.HORIZONTAL));
  
      Canvas canvasTopRight = new Canvas(top, SWT.NONE);
      canvasTopRight.setBackground(SWTResourceManager
              .getColor(SWT.COLOR_BLUE));
      canvasTopRight.setLayout(new FillLayout(SWT.HORIZONTAL));
  
      Canvas canvasBottomLeft = new Canvas(bottom, SWT.NONE);
      canvasBottomLeft.setBackground(SWTResourceManager
              .getColor(SWT.COLOR_DARK_YELLOW));
      canvasBottomLeft.setLayout(new FillLayout(SWT.HORIZONTAL));
  
      Canvas canvasBottomMiddle = new Canvas(bottom, SWT.NONE);
      canvasBottomMiddle.setBackground(SWTResourceManager
              .getColor(SWT.COLOR_DARK_RED));
      canvasBottomMiddle.setLayout(new FillLayout(SWT.HORIZONTAL));
  
      Canvas canvasBottomRight = new Canvas(bottom, SWT.NONE);
      canvasBottomRight.setBackground(SWTResourceManager
              .getColor(SWT.COLOR_DARK_GREEN));
      canvasBottomRight.setLayout(new FillLayout(SWT.HORIZONTAL));
  
      top.setWeights(new int[] { 2, 2, 2 });
      bottom.setWeights(new int[] { 2, 2, 2 });
  
      canvasBottomLeft.addListener(SWT.Resize, new Listener() {
          @Override
          public void handleEvent(Event arg0) {
              top.setWeights(bottom.getWeights());
          }
      });
  
      canvasTopLeft.addListener(SWT.Resize, new Listener() {
          @Override
          public void handleEvent(Event arg0) {
              bottom.setWeights(top.getWeights());
          }
      });
  
      shell.pack();
      shell.open();
  
      while (!shell.isDisposed()) {
          if (!display.readAndDispatch()) {
              display.sleep();
          }
      }
      display.dispose();
  }
  </code></pre>
  
  <p>}</p>