diff dwtx/novocode/ishell/InternalShell.d @ 188:e3780acbbf80

Added ported sources from Novocode, thanks to WasserDragoon
author Frank Benoit <benoit@tionex.de>
date Sun, 26 Oct 2008 14:54:39 +0100
parents
children 71ca5bcf2307
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/novocode/ishell/InternalShell.d	Sun Oct 26 14:54:39 2008 +0100
@@ -0,0 +1,399 @@
+/*******************************************************************************
+ * Copyright (c) 2005 Stefan Zeiger and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.novocode.com/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Stefan Zeiger (szeiger@novocode.com) - initial API and implementation
+ *******************************************************************************/
+
+module dwtx.novocode.ishell.InternalShell;
+
+import dwt.DWT;
+import dwt.DWTException;
+import dwt.graphics.Image;
+import dwt.graphics.Point;
+import dwt.graphics.Rectangle;
+import dwt.layout.FormAttachment;
+import dwt.layout.FormData;
+import dwt.layout.FormLayout;
+import dwt.widgets.Composite;
+import dwt.widgets.Control;
+import dwt.widgets.Event;
+import dwt.widgets.Listener;
+import dwt.widgets.Menu;
+
+import dwtx.novocode.SizeBorder;
+import dwtx.novocode.SizeGrip;
+import dwtx.novocode.ishell.DesktopForm;
+import dwtx.novocode.ishell.internal.TitleBar;
+import dwtx.novocode.ishell.internal.TitleBarButton;
+
+alias char[] String;
+
+
+/**
+ * An internal shell which can be placed on a DesktopForm.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>RESIZE, CLOSE, MAX, ON_TOP, TOOL, NO_RADIO_GROUP</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * </p>
+ *
+ * @author Stefan Zeiger (szeiger@novocode.com)
+ * @since Jan 21, 2005
+ * @version $Id: InternalShell.java 344 2005-07-09 22:37:51 +0000 (Sat, 09 Jul 2005) szeiger $
+ */
+
+// [TODO] Support styles NO_TRIM, BORDER, TITLE
+// [TODO] Separate "minimized" from "not visible"
+
+class InternalShell : Composite
+{
+  private static const int BORDER_SIZE = 4;
+
+  private Composite contentPane;
+  private TitleBar titleBar;
+  private SizeGrip sizeGrip;
+  private SizeBorder sizeBorder;
+  private int minWidth = 112;
+  private int minHeight;
+  private DesktopForm desktop;
+  private bool maximized;
+  private Rectangle pluralizedBounds;
+  private int titleHeight;
+  private int style;
+  private TitleBarButton closeButton, maxButton, minButton;
+
+  Control focusControl;
+
+  
+  this(DesktopForm parent, int style)
+  {
+    super(parent, checkStyle(style));
+    this.desktop = parent;
+    this.style = style;
+    setBackground(getDisplay().getSystemColor(DWT.COLOR_WIDGET_BACKGROUND));
+    FormLayout layout = new FormLayout();
+    setLayout(layout);
+    FormData fd;
+
+    titleBar = new TitleBar(this, style & (DWT.CLOSE | DWT.RESIZE | DWT.MAX | DWT.TOOL | DWT.MIN));
+    titleHeight = titleBar.computeSize(DWT.DEFAULT, DWT.DEFAULT, true).y;
+    
+    Control leftButton = null;
+
+    if((style & (DWT.CLOSE | DWT.MAX | DWT.MIN)) !is 0)
+    {
+      closeButton = new TitleBarButton(this, DWT.CLOSE);
+      if((style & DWT.CLOSE) is 0) closeButton.setEnabled(false);
+      closeButton.addListener(DWT.Selection, dgListener(&closeListener));
+      fd = new FormData(titleHeight, titleHeight);
+      if(leftButton !is null) fd.right = new FormAttachment(leftButton);
+      else fd.right = new FormAttachment(100, -BORDER_SIZE);
+      fd.top = new FormAttachment(0, BORDER_SIZE);
+      closeButton.setLayoutData(fd);
+      leftButton = closeButton;
+
+      if((style & (DWT.MAX|DWT.MIN)) !is 0)
+      {
+        maxButton = new TitleBarButton(this, DWT.MAX);
+        if((style & DWT.MAX) is 0) maxButton.setEnabled(false);
+        maxButton.addListener(DWT.Selection, dgListener(&maximizeListener));
+        fd = new FormData(titleHeight, titleHeight);
+        if(leftButton !is null) fd.right = new FormAttachment(leftButton);
+        else fd.right = new FormAttachment(100, -BORDER_SIZE);
+        fd.top = new FormAttachment(0, BORDER_SIZE);
+        maxButton.setLayoutData(fd);
+        leftButton = maxButton;
+
+        minButton = new TitleBarButton(this, DWT.MIN);
+        if((style & DWT.MIN) is 0) minButton.setEnabled(false);
+        minButton.addListener(DWT.Selection, dgListener(&minimizeListener));
+        fd = new FormData(titleHeight, titleHeight);
+        if(leftButton !is null) fd.right = new FormAttachment(leftButton);
+        else fd.right = new FormAttachment(100, -BORDER_SIZE);
+        fd.top = new FormAttachment(0, BORDER_SIZE);
+        minButton.setLayoutData(fd);
+        leftButton = minButton;
+      }
+    }
+
+    fd = new FormData();
+    fd.left = new FormAttachment(0, BORDER_SIZE);
+    if(leftButton !is null) fd.right = new FormAttachment(leftButton);
+    else fd.right = new FormAttachment(100, -BORDER_SIZE);
+    fd.top = new FormAttachment(0, BORDER_SIZE);
+    titleBar.setLayoutData(fd);
+    
+    contentPane = new Composite(this, DWT.NONE);
+    fd = new FormData();
+    fd.left = new FormAttachment(0, BORDER_SIZE);
+    fd.right = new FormAttachment(100, -BORDER_SIZE);
+    fd.top = new FormAttachment(titleBar, 1);
+    fd.bottom = new FormAttachment(100, -BORDER_SIZE);
+    contentPane.setLayoutData(fd);
+
+    sizeBorder = new SizeBorder(this, this, DWT.BORDER);
+    sizeBorder.setBorderWidth(BORDER_SIZE);
+    fd = new FormData();
+    fd.left = new FormAttachment(0);
+    fd.right = new FormAttachment(100);
+    fd.top = new FormAttachment(0);
+    fd.bottom = new FormAttachment(100);
+    sizeBorder.setLayoutData(fd);
+    
+    minHeight = titleHeight + 2*BORDER_SIZE;
+    sizeBorder.setMinimumShellSize(minWidth, minHeight);
+    sizeBorder.setCornerSize(titleHeight + BORDER_SIZE);
+    if((style & DWT.RESIZE) is 0) sizeBorder.setEnabled(false);
+    
+    setSize(320, 240);
+    setVisible(false);
+    
+    desktop.manage(this);
+  }
+
+
+  private void closeListener(Event event)
+  {
+      close();
+  }
+
+
+  private void maximizeListener(Event event)
+  {
+      setMaximized(!maximized);
+  }
+
+
+  private void minimizeListener(Event event)
+  {
+      setMinimized(true);
+  }
+
+
+  private static int checkStyle(int style)
+  {
+    int mask = DWT.NO_RADIO_GROUP;
+    style &= mask;
+    return style;
+  }
+
+
+  public int getStyle()
+  {
+    return style;
+  }
+
+
+  public Composite getContentPane() { return contentPane; }
+
+
+  public void setText(String s) { titleBar.setText(s); }
+
+  public String getText() { return titleBar.getText(); }
+
+
+  public void setCustomMenu(Menu menu) { titleBar.setMenu(menu); }
+
+  public Menu getCustomMenu() { return titleBar.getMenu(); }
+
+
+  public void setImage(Image image) { titleBar.setImage(image); }
+
+  public Image getImage() { return titleBar.getImage(); }
+
+
+  public void createSizeGrip(int style)
+  {
+    checkWidget();
+    if(sizeGrip !is null)
+      throw new DWTException("SizeGrip was already created");
+    if((this.style & DWT.RESIZE) is 0)
+      throw new DWTException("Cannot create SizeGrip for InternalShell without style RESIZE");
+    sizeGrip = new SizeGrip(this, this, style);
+    sizeGrip.setBackground(contentPane.getBackground());
+    sizeGrip.moveAbove(contentPane);
+    FormData fd = new FormData();
+    fd.right = new FormAttachment(100, -BORDER_SIZE);
+    fd.bottom = new FormAttachment(100, -BORDER_SIZE);
+    sizeGrip.setLayoutData(fd);
+    sizeGrip.setMinimumShellSize(minWidth, minHeight);
+    if(isVisible()) layout(true);
+  }
+  
+  
+  public Point computeSize(int wHint, int hHint, bool changed)
+  {
+    Point p = super.computeSize(wHint, hHint, changed);
+    if(p.x < minWidth) p.x = minWidth;
+    if(p.y < minHeight) p.y = minHeight;
+    return p;
+  }
+  
+  
+  public void setSize(int width, int height)
+  {
+    if(width < minWidth) width = minWidth;
+    if(height < minHeight) height = minHeight;
+    super.setSize(width, height);
+  }
+
+  
+  public void setBounds(int x, int y, int width, int height)
+  {
+    if(width < minWidth) width = minWidth;
+    if(height < minHeight) height = minHeight;
+    super.setBounds(x, y, width, height);
+  }
+
+
+  public void setMinimumSize(int width, int height)
+  {
+    checkWidget();
+    minWidth = width;
+    minHeight = height;
+    sizeGrip.setMinimumShellSize(minWidth, minHeight);
+    sizeBorder.setMinimumShellSize(minWidth, minHeight);
+    Point size = getSize();
+    if(size.x < minWidth || size.y < minHeight)
+      setSize(Math.max(minWidth, size.x), Math.max(minHeight, size.y));
+  }
+
+
+  public void close()
+  {
+    Event event = new Event();
+    notifyListeners(DWT.Close, event);
+    if(event.doit && !isDisposed()) dispose();
+  }
+  
+  
+  public void open()
+  {
+    desktop.activate(this);
+    setVisible(true);
+    setFocus();
+  }
+  
+  
+  public void setVisible(bool visible)
+  {
+    if(!visible) desktop.shellVisibilityChanged(this, false);
+    super.setVisible(visible);
+    if(visible) desktop.shellVisibilityChanged(this, true);
+  }
+  
+  
+  public void setActive()
+  {
+    desktop.activate(this);
+  }
+  
+  
+  public void setMaximized(bool maximized)
+  {
+    checkWidget();
+    if(this.maximized is maximized) return;
+    setMaximizedWithoutNotification(maximized);
+    desktop.shellMaximizedOrRestored(this, maximized);
+  }
+
+  
+  public void setMinimized(bool minimized)
+  {
+    checkWidget();
+    bool wasMaximized = maximized;
+    setVisible(!minimized);
+    maximized = wasMaximized;
+  }
+  
+  
+  public bool getMinimized()
+  {
+    return getVisible();
+  }
+
+  
+  void setMaximizedWithoutNotification(bool maximized)
+  {
+    if(this.maximized is maximized) return;
+    this.maximized = maximized;
+    if(maximized)
+    {
+      pluralizedBounds = getBounds();
+      desktopResized(desktop.getClientArea());
+    }
+    else
+    {
+      setBounds(pluralizedBounds.x,pluralizedBounds.y,pluralizedBounds.width,pluralizedBounds.height);
+    }
+    // Note: This method may be called in a Dispose event for this object
+    if(sizeGrip !is null && !sizeGrip.isDisposed()) sizeGrip.setVisible(!maximized);
+    if(!sizeBorder.isDisposed()) sizeBorder.setEnabled(!maximized && (style & DWT.RESIZE) !is 0);
+    if(maxButton !is null && !maxButton.isDisposed()) maxButton.redraw();
+  }
+
+  
+  public bool getMaximized()
+  {
+    checkWidget();
+    return maximized;
+  }
+  
+  
+  void redrawDecorationsAfterActivityChange()
+  {
+    // Note: This method may be called in a Dispose event for this object
+    if(!titleBar.isDisposed()) titleBar.redraw();
+    if(closeButton !is null && !closeButton.isDisposed()) closeButton.redraw();
+    if(maxButton !is null && !maxButton.isDisposed()) maxButton.redraw();
+    if(minButton !is null && !minButton.isDisposed()) minButton.redraw();
+  }
+  
+  
+  void desktopResized(Rectangle deskCA)
+  {
+    if(maximized)
+    {
+      int hideTitle = desktop.getShowMaximizedTitle() ? 0 : (titleHeight+1);
+      setBounds(deskCA.x - BORDER_SIZE,
+        deskCA.y - BORDER_SIZE - hideTitle,
+        deskCA.width + 2*BORDER_SIZE,
+        deskCA.height + 2*BORDER_SIZE + hideTitle);
+    }
+    else forceVisibleLocation(deskCA);
+  }
+  
+  
+  public bool setFocus()
+  {
+    if(focusControl !is null && focusControl !is this && !focusControl.isDisposed())
+      return focusControl.setFocus();
+    return super.setFocus();
+  }
+  
+  
+  public bool isActiveShell()
+  {
+    return desktop.getActiveShell() is this;
+  }
+  
+  
+  private void forceVisibleLocation(Rectangle deskCA)
+  {
+    Point p = getLocation();
+    Point minGrabSize = titleBar.getMinGrabSize();
+    int x = p.x, y = p.y;
+    int minX = minGrabSize.x + BORDER_SIZE, minY = minGrabSize.y + BORDER_SIZE;
+    x = Math.min(Math.max(x, deskCA.x+minY), deskCA.x+deskCA.width-minX);
+    y = Math.min(Math.max(y, deskCA.y+minY), deskCA.y+deskCA.height-minY);
+    if(x != p.x || y != p.y) setLocation(x, y);
+  }
+}