/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.util.gui; import java.awt.Adjustable; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JViewport; import javax.swing.ScrollPaneConstants; import javax.swing.event.CellEditorListener; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicBorders; import com.servoy.j2db.smart.dataui.StyledEnablePanel; import com.servoy.j2db.ui.IScrollPane; import com.servoy.j2db.util.EnablePanel; import com.servoy.j2db.util.EnableScrollPanel; import com.servoy.j2db.util.ISkinnable; import com.servoy.j2db.util.Utils; /** * @author jblok */ public class PartsScrollPane extends EnablePanel implements javax.swing.plaf.UIResource, IScrollPane { protected StyledEnablePanel innerPanel; protected FixedJScrollPane scroll; protected EnablePanel scrollColumnHeaderPanel; public PartsScrollPane() { setLayout(new VerticalBorderLayout()); innerPanel = new StyledEnablePanel(); innerPanel.setLayout(new BorderLayout()); add(innerPanel, BorderLayout.CENTER); scroll = new PartsScroller(); setBorder(BasicBorders.getTextFieldBorder()); // setBorder(scroll.getBorder());//couses excpetion scroll.setBorder(BorderFactory.createEmptyBorder()); innerPanel.add(scroll, BorderLayout.CENTER); scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollColumnHeaderPanel = new EnablePanel(); scrollColumnHeaderPanel.setLayout(new BorderLayout()); scrollColumnHeaderPanel.setOpaque(false); scroll.setColumnHeaderView(scrollColumnHeaderPanel); if (scroll.getColumnHeader() != null) scroll.getColumnHeader().setOpaque(false); setOpaque(true); } class PartsScroller extends EnableScrollPanel { @Override public JScrollBar createHorizontalScrollBar() { return new EditListScrollBar(this, Adjustable.HORIZONTAL); } @Override public JScrollBar createVerticalScrollBar() { return new EditListScrollBar(this, Adjustable.VERTICAL); } /* * (non-Javadoc) * * @see java.awt.Component#processMouseWheelEvent(java.awt.event.MouseWheelEvent) */ @Override protected void processMouseWheelEvent(MouseWheelEvent e) { int value = getVerticalScrollBar().getValue(); super.processMouseWheelEvent(e); if (value == getVerticalScrollBar().getValue()) { // if nothing happened Container p = getParent(); while (p != null && !(p instanceof PartsScroller)) { p = p.getParent(); } if (p instanceof PartsScroller) { p.dispatchEvent(new MouseWheelEvent(e.getComponent(), e.getID(), e.getWhen(), e.getModifiersEx(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getScrollType(), e.getScrollAmount(), e.getWheelRotation())); } } } //Very special ScrollBar implementation which send its change only on mouse release must be innerclass protected class EditListScrollBar extends ScrollBar implements ISkinnable { private static final long serialVersionUID = 1L; protected JScrollPane scroller; protected int iValue = -1; public EditListScrollBar(JScrollPane scroll, int orientation) { super(orientation); this.scroller = scroll; } @Override public int getUnitIncrement(int direction) { int unitInc = super.getUnitIncrement(direction); if (unitInc <= 5) { unitInc = 20; } return unitInc; } @Override public void setUI(ComponentUI ui) { super.setUI(ui); } private final boolean continuesScrolling = false; /** * @see Adjustable#setValue(int) */ @Override public void setValue(int v) { if (iValue == -1) { super.setValue(v); } else { iValue = v; if (continuesScrolling) { super.setValue(v); } } } /** * @see Component#processMouseMotionEvent(MouseEvent) */ @Override protected void processMouseMotionEvent(MouseEvent e) { if (iValue == -1 && e.getID() == MouseEvent.MOUSE_DRAGGED) { iValue = getValue(); } super.processMouseMotionEvent(e); } /** * @see Component#processMouseEvent(MouseEvent) */ @Override protected void processMouseEvent(MouseEvent e) { if (e.getID() == MouseEvent.MOUSE_PRESSED) { if (scroller.getViewport().getView() instanceof CellEditorListener) { ((CellEditorListener)scroller.getViewport().getView()).editingStopped(null); super.requestFocus(); } } if (iValue != -1 && e.getID() == MouseEvent.MOUSE_RELEASED) { super.setValue(iValue); iValue = -1; } super.processMouseEvent(e); } } } public JComponent getTitleHeader() { return titleHeader; } protected JComponent titleHeader; public void setTitleHeader(JComponent c) { if (c != null) { if (titleHeader != null) { remove(titleHeader); } add(c, BorderLayout.NORTH); this.titleHeader = c; } } public JComponent getHeader() { return header; } protected JComponent header; public void setHeader(JComponent c) { if (c != null) { removeOldComponent(scrollColumnHeaderPanel, c.getName()); if (header != null) { scrollColumnHeaderPanel.remove(header); } scrollColumnHeaderPanel.add(c, BorderLayout.CENTER); scrollColumnHeaderPanel.validate(); this.header = c; // need this to have the right bgcolor in the header above the content scrollbar scroll.setBackground(this.header.getBackground()); } } public void setViewportView(JComponent c) { if (c != null) { scroll.setViewportView(c); // need this to have the right bgcolor in the header above the content scrollbar scroll.setBackground(header != null ? header.getBackground() : scroll.getViewport().getBackground()); } } public JViewport getViewport() { if (scroll != null) { return scroll.getViewport(); } return null; } public JScrollBar getVerticalScrollBar() { return scroll.getVerticalScrollBar(); } public JScrollBar getHorizontalScrollBar() { return scroll.getHorizontalScrollBar(); } public void setHorizontalScrollBarPolicy(int policy) { scroll.setHorizontalScrollBarPolicy(policy); } public void setVerticalScrollBarPolicy(int policy) { scroll.setVerticalScrollBarPolicy(policy); } public JComponent getLeadingGrandSummary() { return leadingGrandSummary; } protected JComponent leadingGrandSummary; public void setLeadingGrandSummary(JComponent c) { if (c != null) { removeOldComponent(scrollColumnHeaderPanel, c.getName()); if (leadingGrandSummary != null) { scrollColumnHeaderPanel.remove(leadingGrandSummary); } scrollColumnHeaderPanel.add(c, BorderLayout.SOUTH); scrollColumnHeaderPanel.validate(); this.leadingGrandSummary = c; } } public JComponent getTrailingGrandSummary() { return trailingGrandSummary; } protected JComponent trailingGrandSummary; public void setTrailingGrandSummary(JComponent c) { if (c != null) { if (trailingGrandSummary != null) { innerPanel.remove(trailingGrandSummary); } innerPanel.add(c, BorderLayout.SOUTH); innerPanel.validate(); this.trailingGrandSummary = c; } } public JComponent getFooter() { return footer; } protected JComponent footer; public void setFooter(JComponent c) { if (c != null) { removeOldComponent(this, c.getName()); if (footer != null) { remove(footer); } add(c, BorderLayout.SOUTH); this.footer = c; } } public JComponent getWest() { return west; } protected JComponent west; public void setWest(JComponent c) { if (c != null) { add(c, BorderLayout.LINE_START); } else { if (west != null) remove(west); } this.west = c; } public void destroy() { removeAll(); footer = null; header = null; leadingGrandSummary = null; trailingGrandSummary = null; west = null; } @Override public void setEnabled(boolean b) { if (west != null) west.setEnabled(b); if (header != null) header.setEnabled(b); if (footer != null) footer.setEnabled(b); if (leadingGrandSummary != null) leadingGrandSummary.setEnabled(b); if (trailingGrandSummary != null) trailingGrandSummary.setEnabled(b); super.setEnabled(b); } protected void removeOldComponent(JPanel panel, String name) { if (Utils.stringIsEmpty(name)) { return; } Component[] components = panel.getComponents(); for (Component element : components) { if (!Utils.stringIsEmpty(element.getName()) && name.equals(element.getName())) { panel.remove(element); break; } } } // Just make sure that when the opacity is set, it gets propagated to all child parts. @Override public void setOpaque(boolean isOpaque) { super.setOpaque(isOpaque); if (innerPanel != null) innerPanel.setOpaque(isOpaque); if (scroll != null) { scroll.setOpaque(isOpaque); if (scroll.getViewport() != null) { scroll.getViewport().setOpaque(isOpaque); JComponent a = (JComponent)scroll.getViewport().getView(); if (a != null) { a.setOpaque(isOpaque); if (!isOpaque) a.setBackground(new Color(0, 0, 0, 254)); } } if (scroll.getColumnHeader() != null) { scroll.getColumnHeader().setOpaque(isOpaque); } } if (west != null) west.setOpaque(isOpaque); if (titleHeader != null) titleHeader.setOpaque(isOpaque); if (header != null) header.setOpaque(isOpaque); if (footer != null) footer.setOpaque(isOpaque); if (leadingGrandSummary != null) leadingGrandSummary.setOpaque(isOpaque); if (trailingGrandSummary != null) trailingGrandSummary.setOpaque(isOpaque); } }