/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.skin; import java.text.NumberFormat; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; /** * <p> * Parameters: * <dl> * <dt>.startpos</dt> * <dd>Position in pixels of where to start the sash by default</dd> * <dt></dt> * <dd></dd> * </dl> * * @author TuxPaper * @created Oct 18, 2006 * */ public class SWTSkinObjectSash extends SWTSkinObjectBasic { /** * Fast Drag disables resizing left and right sides on each mouse move (when * mouse is down) * * Two problems with disabling FASTDRAG: * 1) The places we use the sash currently have very slow re-rendering * 2) when the user drags out of bounds (minsize, etc), and we set doit * to false. When the user lifts up the mouse button, we get one * selection event at the old position (because we cancelled) * * #2 can be fixed... #1 not so much.. */ private static final boolean FASTDRAG = true; protected String sControlBefore; protected String sControlAfter; private Composite createOn; private final boolean isVertical; private Sash sash; private Composite parentComposite; private Composite above = null; private int aboveMin = 0; private Composite below = null; private int belowMin = 0; private String sBorder; private SWTSkinObject soAbove; private SWTSkinObject soBelow; public SWTSkinObjectSash(final SWTSkin skin, final SWTSkinProperties properties, final String sID, final String sConfigID, String[] typeParams, SWTSkinObject parent, final boolean bVertical) { super(skin, properties, sID, sConfigID, "sash", parent); isVertical = bVertical; int style = bVertical ? SWT.VERTICAL : SWT.HORIZONTAL; if (typeParams.length > 2) { sControlBefore = typeParams[1]; sControlAfter = typeParams[2]; } if (parent == null) { createOn = skin.getShell(); } else { createOn = (Composite) parent.getControl(); } if (createOn == null || createOn.isDisposed()) { Debug.out("Can not create " + sID + " because parent is null or disposed"); return; } sash = new Sash(createOn, style); int splitAtPX = COConfigurationManager.getIntParameter("v3." + sID + ".splitAtPX", -1); if (splitAtPX >= 0) { sash.setData("PX", new Long(splitAtPX)); } else { String sPos = properties.getStringValue(sConfigID + ".startpos"); if (sPos != null) { try { long l = NumberFormat.getInstance().parse(sPos).longValue(); sash.setData("PX", new Long(l)); } catch (Exception e) { Debug.out(e); } } } parentComposite = createOn; SWTSkinObject soInitializeSashAfterCreated = parent == null ? this : parent; soInitializeSashAfterCreated.addListener(new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == SWTSkinObjectListener.EVENT_CREATED) { initialize(); } return null; } }); sBorder = properties.getStringValue(sConfigID + ".border", (String) null); if (sBorder != null) { sash.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { e.gc.setForeground(e.gc.getDevice().getSystemColor( SWT.COLOR_WIDGET_NORMAL_SHADOW)); Point size = sash.getSize(); if (bVertical) { e.gc.drawLine(0, 0, 0, size.y); if (!sBorder.startsWith("thin-top")) { int x = size.x - 1; e.gc.drawLine(x, 0, x, 0 + size.y); } } else { e.gc.drawLine(0, 0, 0 + size.x, 0); if (!sBorder.startsWith("thin-top")) { int y = size.y - 1; e.gc.drawLine(0, y, 0 + size.x, y); } } } }); } setControl(sash); } /** * * * @since 3.1.0.1 */ protected void initialize() { SWTSkinObject skinObject; skinObject = skin.getSkinObjectByID(sControlBefore); if (skinObject != null) { soAbove = skinObject; above = (Composite) skinObject.getControl(); aboveMin = skinObject.getProperties().getIntValue( getConfigID() + ".above" + (isVertical ? ".minwidth" : ".minheight"), 0); boolean aboveVisible = COConfigurationManager.getBooleanParameter("v3." + sID + ".aboveVisible", true); soAbove.setVisible(aboveVisible); } skinObject = skin.getSkinObjectByID(sControlAfter); if (skinObject != null) { soBelow = skinObject; below = (Composite) skinObject.getControl(); } if (below == null) { return; } belowMin = skinObject==null?0:skinObject.getProperties().getIntValue( getConfigID() + ".below" + (isVertical ? ".minwidth" : ".minheight"), 0); Listener l = new Listener() { public void handleEvent(Event e) { if (e.type == SWT.MouseUp) { if (e.button == 3 || (e.button == 1 && (e.stateMask & SWT.MOD1) > 0)) { String sPos = properties.getStringValue(sConfigID + ".startpos"); if (sPos == null) { return; } try { long l = NumberFormat.getInstance().parse(sPos).longValue(); sash.setData("PX", new Long(l)); // FALL THROUGH e.type = SWT.Show; } catch (Exception ex) { Debug.out(ex); return; } } else { return; } } if (e.type == SWT.Show) { // delay so soAbove's show gets triggered Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { handleShow(); } }); } else if (e.type == SWT.Selection) { if (FASTDRAG && e.detail == SWT.DRAG) { return; } Rectangle area = parentComposite.getBounds(); FormData aboveData = (FormData) above.getLayoutData(); //FormData belowData = (FormData) below.getLayoutData(); if (isVertical) { // Need to figure out if we have to use border width elsewhere // in calculations (probably) aboveData.width = e.x - above.getBorderWidth(); if (aboveData.width < aboveMin) { aboveData.width = aboveMin; e.x = aboveMin; } else { int excess = area.width - (above.getBorderWidth() * 2) - sash.getSize().x; if (excess - aboveData.width < belowMin) { aboveData.width = excess - belowMin; e.doit = false; } } } else { aboveData.height = e.y - above.getBorderWidth(); if (aboveData.height < aboveMin) { aboveData.height = aboveMin; e.y = aboveMin; } else { int excess = area.height - (above.getBorderWidth() * 2) - sash.getSize().y; if (excess - aboveData.height < belowMin) { aboveData.height = excess - belowMin; e.doit = false; } } } parentComposite.layout(true); double aboveNewSize; if (isVertical) { aboveNewSize = above.getBounds().width + (sash.getSize().x / 2.0); } else { aboveNewSize = above.getBounds().height + (sash.getSize().y / 2.0); } sash.setData("PX", new Long((long) aboveNewSize)); } } }; sash.addListener(SWT.Selection, l); sash.addListener(SWT.MouseUp, l); sash.getShell().addListener(SWT.Show, l); handleShow(); } public void dispose() { Long px = (Long) sash.getData("PX"); if (px != null && px.longValue() != 0) { COConfigurationManager.setParameter("v3." + sID + ".splitAtPX", px.longValue()); } super.dispose(); } /** * @param e * * @since 3.1.0.1 */ protected void handleShow() { Long px = (Long) sash.getData("PX"); if (px == null) { return; } int newAboveSize; if (soAbove.isVisible()) { newAboveSize = px.intValue(); if (newAboveSize < aboveMin) { newAboveSize = aboveMin; } } else { newAboveSize = 0; } FormData aboveData = (FormData) above.getLayoutData(); if (aboveData == null) { aboveData = Utils.getFilledFormData(); above.setLayoutData(aboveData); } if (isVertical) { aboveData.width = newAboveSize; } else { aboveData.height = newAboveSize; } parentComposite.layout(true); } /** * @param below * @param bVertical * @param parentComposite * @param sash * @param above * */ protected void setPercent(double pctAbove, Control sash, Composite above, Composite below, boolean bVertical, Control parentComposite, int minAbove, int belowMin) { FormData aboveData = (FormData) above.getLayoutData(); if (aboveData == null) { return; } boolean layoutNeeded = false; if (bVertical) { int parentWidth = parentComposite.getBounds().width - (parentComposite.getBorderWidth() * 2) - sash.getSize().x; int newWidth = (int) (parentWidth * pctAbove); if (newWidth != aboveData.width) { aboveData.width = newWidth; layoutNeeded = true; } if (pctAbove != 0.0 && parentWidth - aboveData.width - sash.getSize().x < minAbove) { aboveData.width = parentWidth - minAbove - sash.getSize().x; layoutNeeded = true; //d = (double) (aboveData.width + sash.getSize().x) / parentWidth; } else if (aboveData.width < belowMin) { layoutNeeded = true; aboveData.width = belowMin; } sash.setData("PX", new Long(aboveData.width)); } else { int parentHeight = parentComposite.getBounds().height - (parentComposite.getBorderWidth() * 2) - sash.getSize().y; int newHeight = (int) (parentHeight * pctAbove); if (aboveData.height != newHeight) { aboveData.height = newHeight; layoutNeeded = true; } if (pctAbove != 0.0 && parentHeight - aboveData.height < minAbove && parentHeight >= minAbove) { aboveData.height = parentHeight - minAbove; layoutNeeded = true; } else if (aboveData.height < belowMin) { layoutNeeded = true; aboveData.height = belowMin; } sash.setData("PX", new Long(aboveData.height)); } if (layoutNeeded) { above.getParent().layout(); } } public void setBelowSize(final int px) { Utils.execSWTThread(new AERunnable() { public void runSupport() { int sashHeight = isVertical ? sash.getSize().x : sash.getSize().y; int parentHeight = parentComposite.getBounds().height - (parentComposite.getBorderWidth() * 2); int wantAboveSize = parentHeight - sashHeight - px; sash.setData("PX", new Long(wantAboveSize)); handleShow(); } }); } public void setAboveSize(final int px) { Utils.execSWTThread(new AERunnable() { public void runSupport() { sash.setData("PX", new Long(px)); handleShow(); } }); } public void resetWidth() { Utils.execSWTThread(new AERunnable() { public void runSupport() { String sPos = properties.getStringValue(sConfigID + ".startpos"); COConfigurationManager.removeParameter("v3." + sID + ".splitAt"); COConfigurationManager.removeParameter("v3." + sID + ".splitAtPX"); if (sPos != null) { sash.setData("PX", null); try { int l = NumberFormat.getInstance().parse(sPos).intValue(); setAboveSize(l); } catch (Exception e) { Debug.out(e); } } } }); } public boolean isAboveVisible() { if (soAbove == null || soAbove.isDisposed()) { return false; } return soAbove.isVisible(); } public void setAboveVisible(boolean visible) { if (soAbove == null) { return; } COConfigurationManager.setParameter("v3." + sID + ".aboveVisible", visible); soAbove.setVisible(visible); handleShow(); } }