1 19 package org.netbeans.modules.subversion.ui.diff; 20 21 import java.awt.BorderLayout ; 22 import java.awt.Color ; 23 import java.awt.Component ; 24 import java.awt.Dimension ; 25 import java.awt.Graphics ; 26 import java.awt.Point ; 27 import java.awt.Rectangle ; 28 import java.awt.event.*; 29 import java.beans.*; 30 import java.beans.PropertyChangeEvent ; 31 import java.beans.PropertyChangeListener ; 32 import javax.swing.*; 33 import javax.swing.JToolBar ; 34 import javax.swing.event.ChangeEvent ; 35 import javax.swing.event.ChangeListener ; 36 import org.netbeans.api.diff.DiffView; 37 import org.netbeans.modules.diff.NestableDiffView; 38 import org.openide.util.NbBundle; 39 import org.openide.awt.UndoRedo; 40 41 55 public class MultiDiffView implements DiffView, PropertyChangeListener { 56 57 58 private final DiffView[] views; 59 60 61 private final NestableDiffView[] nestableViews; 62 63 64 private int currentDifference; 65 66 private PropertyChangeSupport support; 67 68 69 private final Component parent; 70 71 77 private final JScrollBar roller = new JScrollBar(JScrollBar.HORIZONTAL); 78 79 80 private int innerViewsWidth; 81 82 83 private MultiDiffViewPanel panel; 84 85 91 public MultiDiffView(DiffView[] views, Component parent) { 92 this.views = views; 93 nestableViews = new NestableDiffView[views.length]; 94 for (int i = 0; i<views.length; i++) { 95 views[i].addPropertyChangeListener(this); 96 } 97 this.parent = parent; 98 } 99 100 public Component getComponent() { 101 if (panel == null) { 102 panel = new MultiDiffViewPanel(); 103 } 104 return panel; 105 } 106 107 public int getDifferenceCount() { 108 int diffs = 0; 109 for (int i=0; i<views.length; i++) { 110 diffs += views[i].getDifferenceCount(); 111 } 112 return diffs; 113 } 114 115 public boolean canSetCurrentDifference() { 116 boolean ret = true; 117 for (int i=0; i<views.length; i++) { 118 ret &= views[i].canSetCurrentDifference(); 119 } 120 return ret; 121 } 122 123 126 public void setCurrentDifference(int diffNo) throws UnsupportedOperationException { 127 int ypos = 0; 128 for (int i=0; i<views.length; i++) { 129 diffNo -= views[i].getDifferenceCount(); 130 if (diffNo < 0) { 131 int dn = diffNo + views[i].getDifferenceCount(); 132 views[i].setCurrentDifference(dn); 133 if (nestableViews[i] != null) { 134 ypos += nestableViews[i].getChangeY(dn); 135 panel.setViewPosition(new Point (0, ypos)); 136 } 137 for (int j = 0; j<views.length; j++) { 138 if (i == j) continue; 139 views[j].setCurrentDifference(-1); 140 } 141 currentDifference = diffNo; 142 return; 143 } 144 ypos += views[i].getComponent().getHeight(); 145 } 146 } 147 148 public int getCurrentDifference() throws UnsupportedOperationException { 149 return currentDifference; 150 } 151 152 public JToolBar getToolBar() { 153 return views[0].getToolBar(); 154 } 155 156 public void addPropertyChangeListener(PropertyChangeListener l) { 157 getPropertyChangeSupport().addPropertyChangeListener(l); 158 } 159 160 public void removePropertyChangeListener(PropertyChangeListener l) { 161 getPropertyChangeSupport().removePropertyChangeListener(l); 162 } 163 164 public void propertyChange(PropertyChangeEvent evt) { 165 PropertyChangeEvent event = new PropertyChangeEvent (this, evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); 166 getPropertyChangeSupport().firePropertyChange(event); 167 } 168 169 private PropertyChangeSupport getPropertyChangeSupport() { 170 if(support == null) { 171 support = new PropertyChangeSupport(this); 172 } 173 return support; 174 } 175 176 final static class Padding extends JLabel { 177 final Component view; 178 Padding(Component view) { 179 super(NbBundle.getMessage(MultiDiffView.class, "LBL_Diff_Padding"), SwingConstants.CENTER); this.view = view; 181 } 182 public Dimension getPreferredSize() { 183 return view.getSize(); 184 } 185 public Dimension getMinimumSize() { 186 return view.getSize(); 187 } 188 public Dimension getMaximumSize() { 189 return view.getSize(); 190 } 191 } 192 193 private class MoveAction extends AbstractAction { 194 final int increment; 195 MoveAction(int increment) { 196 this.increment = increment; 197 } 198 199 public void actionPerformed(ActionEvent e) { 200 int value = roller.getValue() + increment; 201 if (roller.getMinimum() < value && value < roller.getMaximum()) { 202 roller.setValue(value); 203 } 204 } 205 } 206 207 private class MultiDiffViewPanel extends JPanel implements ChangeListener { 208 209 210 private JScrollPane pane; 211 212 MultiDiffViewPanel() { 213 setFocusable(false); 214 215 ScrollablePanel scrollablePanel = new ScrollablePanel(); 216 217 pane = new JScrollPane(); 218 pane.setBorder(BorderFactory.createEmptyBorder()); 219 pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 220 pane.setViewportView(scrollablePanel); 221 222 for (int i=0; i<views.length; i++) { 223 JComponent c = (JComponent) views[i].getComponent(); 224 if (i == 0) putClientProperty(UndoRedo.class, c.getClientProperty(UndoRedo.class)); 225 scrollablePanel.add(c); 226 if (views[i] instanceof NestableDiffView) { 227 c.putClientProperty(NestableDiffView.class, views[i]); 228 NestableDiffView impl = (NestableDiffView) views[i]; 229 230 KeyStroke stroke; 232 Action action; 233 Object paneKey; 234 235 stroke = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0); 236 action = new MoveAction(-10); 237 paneKey = pane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).get(stroke); 238 pane.getActionMap().put(paneKey, action); 239 240 stroke = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0); 241 action = new MoveAction(10); 242 paneKey = pane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).get(stroke); 243 pane.getActionMap().put(paneKey, action); 244 245 impl.joinScrollPane(pane); 246 nestableViews[i] = impl; 247 } 248 } 249 250 scrollablePanel.add(new Padding(parent)); 254 255 setLayout(new BorderLayout ()); 256 add(pane, BorderLayout.CENTER); 257 add(new SummarySideBar(), BorderLayout.LINE_END); 258 259 JScrollBar vertical = new JScrollBar(JScrollBar.VERTICAL); 260 int padding = vertical.getPreferredSize().width + SUMMARY_WIDTH; 261 roller.setBorder(BorderFactory.createEmptyBorder(0,0,0,padding)); 262 add(roller, BorderLayout.SOUTH); 263 } 264 265 public void layout() { 266 layoutImpl(); 267 } 268 269 public void doLayout() { 270 layoutImpl(); 271 } 272 273 void layoutImpl() { 274 super.layout(); 277 278 for (int i = 0; i<nestableViews.length; i++) { 279 innerViewsWidth = Math.max(innerViewsWidth, nestableViews[i].getInnerWidth()); 280 } 281 282 for (int i = 0; i<nestableViews.length; i++) { 283 nestableViews[i].setInnerWidth(innerViewsWidth); 284 } 285 286 BoundedRangeModel model = roller.getModel(); 287 if (innerViewsWidth > viewWidth()){ 288 roller.setVisible(true); 289 afterResize(); 290 model.addChangeListener(this); 291 } else { 292 roller.setVisible(false); 293 model.removeChangeListener(this); 294 } 295 } 296 297 void afterResize() { 299 final BoundedRangeModel model = roller.getModel(); 300 model.setMaximum(innerViewsWidth); 301 model.setExtent(viewWidth()); 302 model.setValue(0); 303 } 304 305 int viewWidth() { 306 JScrollBar vertical = new JScrollBar(JScrollBar.VERTICAL); 307 int padding = vertical.getPreferredSize().width + SUMMARY_WIDTH; 308 return parent.getWidth() - padding; 309 } 310 311 public void stateChanged(ChangeEvent e) { 312 BoundedRangeModel model = roller.getModel(); 313 if (e.getSource() == model) { 314 if (model.getValueIsAdjusting()) { 315 } 317 for (int i = 0; i<nestableViews.length; i++) { 318 nestableViews[i].setHorizontalPosition(model.getValue()); 319 } 320 } 321 } 322 323 public boolean requestFocusInWindow() { 324 return pane.requestFocusInWindow(); 327 } 328 329 void setViewPosition(Point p) { 330 pane.getViewport().setViewPosition(p); 331 } 332 333 } 334 335 private class ScrollablePanel extends JPanel implements Scrollable { 336 337 ScrollablePanel() { 338 super(); 339 setLayout(new VerticalFlowLayout(parent)); 340 setFocusable(false); 341 } 342 343 public Dimension getPreferredScrollableViewportSize() { 344 return getPreferredSize(); 345 } 346 347 public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { 348 JComponent c = (JComponent) getComponent(0); 349 NestableDiffView inner = (NestableDiffView) c.getClientProperty(NestableDiffView.class); 350 return inner.getInnerScrollableUnitIncrement(visibleRect, orientation, direction); 351 } 352 353 public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { 354 JComponent c = (JComponent) getComponent(0); 355 NestableDiffView inner = (NestableDiffView) c.getClientProperty(NestableDiffView.class); 356 return inner.getInnerScrollableBlockIncrement(visibleRect, orientation, direction); 357 } 358 359 public boolean getScrollableTracksViewportWidth() { 360 return false; } 362 363 public boolean getScrollableTracksViewportHeight() { 364 return false; } 366 } 367 368 final int SUMMARY_WIDTH = 12; 369 final int SCROLLBAR_TOP = 12; final int SCROLLBAR_DOWN = 12; 372 class SummarySideBar extends JComponent { 373 374 public Dimension getPreferredSize() { 375 return new Dimension (SUMMARY_WIDTH, Integer.MAX_VALUE); 376 } 377 378 protected void paintComponent(Graphics g) { 379 super.paintComponent(g); 380 381 Color color = g.getColor(); 382 g.setColor(Color.BLUE); 383 int ybase = 0; 384 float myHeight = getHeight() - SCROLLBAR_TOP - SCROLLBAR_DOWN; 385 float ratio = myHeight / ((float) panel.getHeight()); 386 for (int i = 0; i<views.length; i++) { 387 if (nestableViews[i] == null) { 388 continue; 389 } 390 391 for (int x = 0; x<views[i].getDifferenceCount(); x++) { 392 int ypos = nestableViews[i].getChangeY(x); 393 int y = SCROLLBAR_TOP + (int)((ypos + ybase) * ratio); 394 g.drawRect(0, y, SUMMARY_WIDTH, 1); 395 } 396 ybase += views[i].getComponent().getHeight(); 397 } 398 g.setColor(color); 399 } 400 } 401 } 402 | Popular Tags |