1 /* gtkscrollbarpeer.c -- Native implementation of GtkScrollbarPeer
2    Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 #include <math.h>
40 #include "gtkpeer.h"
41 #include "gnu_java_awt_peer_gtk_GtkComponentPeer.h"
42 #include "gnu_java_awt_peer_gtk_GtkScrollbarPeer.h"
43 
44 #define AWT_ADJUSTMENT_UNIT_INCREMENT 1
45 #define AWT_ADJUSTMENT_UNIT_DECREMENT 2
46 #define AWT_ADJUSTMENT_BLOCK_DECREMENT 3
47 #define AWT_ADJUSTMENT_BLOCK_INCREMENT 4
48 #define AWT_ADJUSTMENT_TRACK 5
49 
50 static jmethodID postAdjustmentEventID;
51 
52 void
cp_gtk_scrollbar_init_jni(void)53 cp_gtk_scrollbar_init_jni (void)
54 {
55   jclass gtkscrollbarpeer;
56 
57   gtkscrollbarpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(),
58                                      "gnu/java/awt/peer/gtk/GtkScrollbarPeer");
59 
60   postAdjustmentEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
61                                                      gtkscrollbarpeer,
62                                                      "postAdjustmentEvent",
63                                                      "(II)V");
64 }
65 
66 #if GTK_MINOR_VERSION > 4
67 static gboolean slider_moved_cb (GtkRange *range,
68                                  GtkScrollType scroll,
69                                  gdouble value,
70                                  jobject obj);
71 #else
72 static void post_change_event_cb (GtkRange *range,
73                                   jobject peer);
74 #endif
75 
76 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_create(JNIEnv * env,jobject obj,jint orientation,jint value,jint min,jint max,jint step_incr,jint page_incr,jint visible_amount)77 Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_create
78   (JNIEnv *env, jobject obj, jint orientation, jint value,
79    jint min, jint max, jint step_incr, jint page_incr, jint visible_amount)
80 {
81   GtkWidget *scrollbar;
82   GtkObject *adj;
83 
84   /* Create global reference and save it for future use */
85   NSA_SET_GLOBAL_REF (env, obj);
86 
87   gdk_threads_enter ();
88 
89   adj = gtk_adjustment_new ((gdouble) value,
90                             (gdouble) min,
91                             (gdouble) max,
92 			    (gdouble) step_incr,
93                             (gdouble) page_incr,
94 			    (gdouble) visible_amount);
95 
96   scrollbar = orientation
97     ? gtk_vscrollbar_new (GTK_ADJUSTMENT (adj))
98     : gtk_hscrollbar_new (GTK_ADJUSTMENT (adj));
99 
100   GTK_RANGE (scrollbar)->round_digits = 0;
101   /* These calls seem redundant but they are not.  They clamp values
102      so that the slider's entirety is always between the two
103      steppers. */
104   gtk_range_set_range (GTK_RANGE (scrollbar), (gdouble) min, (gdouble) max);
105   gtk_range_set_value (GTK_RANGE (scrollbar), (gdouble) value);
106 
107   gdk_threads_leave ();
108 
109   NSA_SET_PTR (env, obj, scrollbar);
110 }
111 
112 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_connectSignals(JNIEnv * env,jobject obj)113 Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_connectSignals
114   (JNIEnv *env, jobject obj)
115 {
116   void *ptr = NSA_GET_PTR (env, obj);
117   jobject *gref = NSA_GET_GLOBAL_REF (env, obj);
118   g_assert (gref);
119 
120   gdk_threads_enter ();
121 
122   /* Scrollbar signals */
123 #if GTK_MINOR_VERSION > 4
124   g_signal_connect (G_OBJECT (ptr), "change-value",
125                     G_CALLBACK (slider_moved_cb), *gref);
126 #else
127   g_signal_connect (G_OBJECT (ptr), "value-changed",
128                     G_CALLBACK (post_change_event_cb), *gref);
129 #endif
130 
131   /* Component signals */
132   cp_gtk_component_connect_signals (G_OBJECT (ptr), gref);
133 
134   gdk_threads_leave ();
135 }
136 
137 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_setLineIncrement(JNIEnv * env,jobject obj,jint amount)138 Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_setLineIncrement
139   (JNIEnv *env, jobject obj, jint amount)
140 {
141   void *ptr;
142   GtkAdjustment *adj;
143 
144   ptr = NSA_GET_PTR (env, obj);
145 
146   gdk_threads_enter ();
147 
148   adj = gtk_range_get_adjustment (GTK_RANGE (ptr));
149   adj->step_increment = (gdouble) amount;
150   gtk_adjustment_changed (adj);
151 
152   gdk_threads_leave ();
153 }
154 
155 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_setPageIncrement(JNIEnv * env,jobject obj,jint amount)156 Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_setPageIncrement
157   (JNIEnv *env, jobject obj, jint amount)
158 {
159   void *ptr;
160   GtkAdjustment *adj;
161 
162   ptr = NSA_GET_PTR (env, obj);
163 
164   gdk_threads_enter ();
165 
166   adj = gtk_range_get_adjustment (GTK_RANGE (ptr));
167   adj->page_increment = (gdouble) amount;
168   gtk_adjustment_changed (adj);
169 
170   gdk_threads_leave ();
171 }
172 
173 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_setValues(JNIEnv * env,jobject obj,jint value,jint visible,jint min,jint max)174 Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_setValues
175   (JNIEnv *env, jobject obj, jint value, jint visible, jint min, jint max)
176 {
177   void *ptr;
178   GtkAdjustment *adj;
179 
180   ptr = NSA_GET_PTR (env, obj);
181 
182   gdk_threads_enter ();
183 
184   adj = gtk_range_get_adjustment (GTK_RANGE (ptr));
185   adj->page_size = (gdouble) visible;
186 
187   gtk_range_set_range (GTK_RANGE (ptr), (gdouble) min, (gdouble) max);
188   gtk_range_set_value (GTK_RANGE (ptr), (gdouble) value);
189 
190   gdk_threads_leave ();
191 }
192 
193 #if GTK_MINOR_VERSION > 4
194 static gboolean
slider_moved_cb(GtkRange * range,GtkScrollType scroll,gdouble value,jobject obj)195 slider_moved_cb (GtkRange *range,
196                  GtkScrollType scroll,
197                  gdouble value,
198                  jobject obj)
199 {
200   GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (range));
201 
202   value = CLAMP (value, adj->lower,
203                  (adj->upper - adj->page_size));
204 
205   if (range->round_digits >= 0)
206     {
207       gdouble power;
208       gint i;
209 
210       i = range->round_digits;
211       power = 1;
212       while (i--)
213         power *= 10;
214 
215       value = floor ((value * power) + 0.5) / power;
216     }
217 
218   switch (scroll)
219     {
220     case GTK_SCROLL_STEP_BACKWARD:
221       (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj, postAdjustmentEventID,
222                                     AWT_ADJUSTMENT_UNIT_DECREMENT,
223                                     (jint) value);
224       break;
225     case GTK_SCROLL_STEP_FORWARD:
226       (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj, postAdjustmentEventID,
227                                     AWT_ADJUSTMENT_UNIT_INCREMENT,
228                                     (jint) value);
229       break;
230     case GTK_SCROLL_PAGE_BACKWARD:
231       (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj, postAdjustmentEventID,
232                                     AWT_ADJUSTMENT_BLOCK_DECREMENT,
233                                     (jint) value);
234       break;
235     case GTK_SCROLL_PAGE_FORWARD:
236       (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj, postAdjustmentEventID,
237                                     AWT_ADJUSTMENT_BLOCK_INCREMENT,
238                                     (jint) value);
239       break;
240     default:
241       /* GTK_SCROLL_JUMP: */
242       (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj, postAdjustmentEventID,
243                                     AWT_ADJUSTMENT_TRACK,
244                                     (jint) value);
245       break;
246     }
247   return FALSE;
248 }
249 #else
250 static void
post_change_event_cb(GtkRange * range,jobject peer)251 post_change_event_cb (GtkRange *range, jobject peer)
252 {
253   GtkAdjustment *adj;
254   adj = gtk_range_get_adjustment (range);
255   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, postAdjustmentEventID,
256 				AWT_ADJUSTMENT_TRACK, (jint) adj->value);
257 }
258 #endif
259