1 /*
   2  * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.scene.control.skin;
  27 
  28 import javafx.scene.control.IndexedCell;
  29 import javafx.scene.control.ScrollBar;
  30 
  31 import com.sun.javafx.util.Utils;
  32 
  33 /**
  34  * This custom ScrollBar is used to map the increment & decrement features
  35  * to pixel based scrolling rather than thumb/track based scrolling, if the
  36  * "virtual" attribute is true.
  37  */
  38 public class VirtualScrollBar extends ScrollBar {
  39     private final VirtualFlow flow;
  40 
  41     private boolean virtual;
  42     
  43     private boolean adjusting;
  44 
  45     public VirtualScrollBar(final VirtualFlow flow) {
  46         this.flow = flow;
  47         
  48         super.valueProperty().addListener(valueModel -> {
  49             if (isVirtual()/* && oldValue != newValue*/) {
  50                 if (adjusting) {
  51                     // no-op
  52                 } else {
  53                     flow.setPosition(getValue());
  54                 }
  55             }
  56         });
  57     }
  58 
  59     public void setVirtual(boolean virtual) {
  60         this.virtual = virtual;
  61     }
  62 
  63     public boolean isVirtual() {
  64         return this.virtual;
  65     }
  66 
  67     @Override public void decrement() {
  68         if (isVirtual()) {
  69             flow.adjustPixels(-10);
  70         } else {
  71             super.decrement();
  72         }
  73     }
  74 
  75     @Override public void increment() {
  76         if (isVirtual()) {
  77             flow.adjustPixels(10);
  78         } else {
  79             super.increment();
  80         }
  81     }
  82     
  83 //    private double lastAdjustValue = 0.0;
  84 
  85     // this method is called when the user clicks in the scrollbar track, so
  86     // we special-case it to allow for page-up and page-down clicking to work
  87     // as expected.
  88     @Override public void adjustValue(double pos) {
  89         if (isVirtual()) {
  90 //            if (pos == lastAdjustValue) {
  91 //                return;
  92 //            }
  93 
  94             adjusting = true;
  95             double oldValue = flow.getPosition();
  96             
  97             double newValue = ((getMax() - getMin()) * Utils.clamp(0, pos, 1))+getMin();
  98             if (newValue < oldValue) {
  99                 IndexedCell cell = flow.getFirstVisibleCell();
 100                 if (cell == null) return;
 101                 flow.showAsLast(cell);
 102             } else if (newValue > oldValue) {
 103                 IndexedCell cell = flow.getLastVisibleCell();
 104                 if (cell == null) return;
 105                 flow.showAsFirst(cell);
 106             }
 107 //            lastAdjustValue = pos;
 108             
 109             adjusting = false;
 110         } else {
 111             super.adjustValue(pos);
 112         }
 113     }
 114 }