1 /*
2  * Copyright (c) 1996, 2016, 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 #include "awt_Toolkit.h"
27 #include "awt_Label.h"
28 #include "awt_Canvas.h"
29 #include "awt_Win32GraphicsDevice.h"
30 
31 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
32  */
33 
34 /***********************************************************************/
35 // Struct for _SetText() method
36 struct SetTextStruct {
37     jobject label;
38     jstring text;
39 };
40 // Struct for _SetAlignment() method
41 struct SetAlignmentStruct {
42     jobject label;
43     jint alignment;
44 };
45 /************************************************************************
46  * AwtLabel fields
47  */
48 
49 jfieldID AwtLabel::textID;
50 jfieldID AwtLabel::alignmentID;
51 
52 
53 /************************************************************************
54  * AwtLabel methods
55  */
56 
AwtLabel()57 AwtLabel::AwtLabel() {
58     m_needPaint = FALSE;
59 }
60 
GetClassName()61 LPCTSTR AwtLabel::GetClassName() {
62     return TEXT("SunAwtLabel");
63 }
64 
65 /* Create a new AwtLabel object and window. */
Create(jobject labelPeer,jobject parent)66 AwtLabel* AwtLabel::Create(jobject labelPeer, jobject parent)
67 {
68     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
69 
70     jobject target = NULL;
71     AwtLabel* awtLabel = NULL;
72 
73     try {
74         if (env->EnsureLocalCapacity(1) < 0) {
75             return NULL;
76         }
77 
78         PDATA pData;
79         AwtCanvas* awtParent;
80 
81         JNI_CHECK_PEER_GOTO(parent, done);
82         awtParent = (AwtCanvas*)pData;
83 
84         target  = env->GetObjectField(labelPeer, AwtObject::targetID);
85         JNI_CHECK_NULL_GOTO(target, "target", done);
86 
87         awtLabel = new AwtLabel();
88 
89         {
90             DWORD style = WS_CHILD | WS_CLIPSIBLINGS;
91 
92             DWORD exStyle = 0;
93             if (GetRTLReadingOrder())
94                 exStyle |= WS_EX_RTLREADING;
95 
96             jint x = env->GetIntField(target, AwtComponent::xID);
97             jint y = env->GetIntField(target, AwtComponent::yID);
98             jint width = env->GetIntField(target, AwtComponent::widthID);
99             jint height = env->GetIntField(target, AwtComponent::heightID);
100             awtLabel->CreateHWnd(env, L"", style, exStyle,
101                                  x, y, width, height,
102                                  awtParent->GetHWnd(),
103                                  NULL,
104                                  ::GetSysColor(COLOR_WINDOWTEXT),
105                                  ::GetSysColor(COLOR_BTNFACE),
106                                  labelPeer);
107         }
108     } catch (...) {
109         env->DeleteLocalRef(target);
110         throw;
111     }
112 
113 done:
114     env->DeleteLocalRef(target);
115     return awtLabel;
116 }
117 
DoPaint(HDC hDC,RECT & r)118 void AwtLabel::DoPaint(HDC hDC, RECT& r)
119 {
120     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
121 
122     if ((r.right-r.left) > 0 && (r.bottom-r.top) > 0 &&
123         m_peerObject != NULL && m_callbacksEnabled) {
124 
125         if (env->EnsureLocalCapacity(3) < 0)
126             return;
127         long x,y;
128         SIZE size;
129 
130         /* self is sun.awt.windows.WLabelPeer  */
131 
132         jobject self = GetPeer(env);
133         DASSERT(self);
134 
135         /* target is java.awt.Label */
136         jobject target = env->GetObjectField(self, AwtObject::targetID);
137         jobject font = GET_FONT(target, self);
138         jstring text = (jstring)env->GetObjectField(target, AwtLabel::textID);
139 
140         size = AwtFont::getMFStringSize(hDC, font, text);
141         ::SetTextColor(hDC, GetColor());
142         /* Redraw whole label to eliminate display noise during resizing. */
143         VERIFY(::GetClientRect(GetHWnd(), &r));
144         VERIFY(::FillRect (hDC, &r, GetBackgroundBrush()));
145         y = (r.top + r.bottom - size.cy) / 2;
146 
147         jint alignment = env->GetIntField(target, AwtLabel::alignmentID);
148         switch (alignment) {
149           case java_awt_Label_CENTER:
150               x = (r.left + r.right - size.cx) / 2;
151               break;
152           case java_awt_Label_RIGHT:
153               x = r.right - 2 - size.cx;
154               break;
155           case java_awt_Label_LEFT:
156           default:
157               x = r.left + 2;
158               break;
159         }
160         /* draw string */
161         if (isEnabled()) {
162             AwtComponent::DrawWindowText(hDC, font, text, x, y);
163         } else {
164             AwtComponent::DrawGrayText(hDC, font, text, x, y);
165         }
166         DoCallback("handlePaint", "(IIII)V",
167                    r.left, r.top, r.right-r.left, r.bottom-r.top);
168         env->DeleteLocalRef(target);
169         env->DeleteLocalRef(font);
170         env->DeleteLocalRef(text);
171     }
172 }
173 
LazyPaint()174 void AwtLabel::LazyPaint()
175 {
176     if (m_callbacksEnabled && m_needPaint ) {
177         ::InvalidateRect(GetHWnd(), NULL, TRUE);
178         m_needPaint = FALSE;
179     }
180 }
181 
Enable(BOOL bEnable)182 void AwtLabel::Enable(BOOL bEnable)
183 {
184     ::EnableWindow(GetHWnd(), bEnable);
185     // Fix for Bug #4038881 Labels don't enable and disable properly
186     // Fix for Bug #4096745 disable()/enable() make AWT components blink
187     // This fix is moved from awt_Component.cpp for Bug #4096745
188     ::InvalidateRect(GetHWnd(), NULL, FALSE);
189     CriticalSection::Lock l(GetLock());
190     VerifyState();
191 }
192 
193 
WmEraseBkgnd(HDC hDC,BOOL & didErase)194 MsgRouting AwtLabel::WmEraseBkgnd(HDC hDC, BOOL& didErase)
195 {
196     RECT r;
197 
198     ::GetClipBox(hDC, &r);
199     ::FillRect(hDC, &r, this->GetBackgroundBrush());
200     didErase = TRUE;
201     return mrConsume;
202 }
203 
WmPaint(HDC)204 MsgRouting AwtLabel::WmPaint(HDC)
205 {
206     PAINTSTRUCT ps;
207     HDC hDC = ::BeginPaint(GetHWnd(), &ps);/* the passed-in HDC is ignored. */
208     DASSERT(hDC);
209 
210     /* fix for 4408606 - incorrect color palette used in 256 color mode */
211 
212     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
213     AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
214 
215     RECT& r = ps.rcPaint;
216     if (!m_callbacksEnabled) {
217         m_needPaint = TRUE;
218     } else {
219         DoPaint(hDC, r);
220     }
221     VERIFY(::EndPaint(GetHWnd(), &ps));
222     return mrConsume;
223 }
224 
WmPrintClient(HDC hDC,LPARAM)225 MsgRouting AwtLabel::WmPrintClient(HDC hDC, LPARAM)
226 {
227     RECT r;
228 
229     // obtain valid DC from GDI stack
230     ::RestoreDC(hDC, -1);
231 
232     ::GetClipBox(hDC, &r);
233     DoPaint(hDC, r);
234     return mrConsume;
235 }
236 
_SetText(void * param)237 void AwtLabel::_SetText(void *param)
238 {
239     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
240 
241     SetTextStruct *sts = (SetTextStruct *)param;
242     jobject self = sts->label;
243     jstring text = sts->text;
244 
245     AwtLabel *l = NULL;
246 
247     PDATA pData;
248     JNI_CHECK_PEER_GOTO(self, ret);
249     l = (AwtLabel *)pData;
250     if (::IsWindow(l->GetHWnd()))
251     {
252         l->SetText(JavaStringBuffer(env, text));
253         VERIFY(::InvalidateRect(l->GetHWnd(), NULL, TRUE));
254     }
255 ret:
256     env->DeleteGlobalRef(self);
257     env->DeleteGlobalRef(text);
258 
259     delete sts;
260 }
261 
_SetAlignment(void * param)262 void AwtLabel::_SetAlignment(void *param)
263 {
264     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
265 
266     SetAlignmentStruct *sas = (SetAlignmentStruct *)param;
267     jobject self = sas->label;
268     jint alignment = sas->alignment;
269 
270     AwtLabel *l = NULL;
271 
272     PDATA pData;
273     JNI_CHECK_PEER_GOTO(self, ret);
274     l = (AwtLabel *)pData;
275     if (::IsWindow(l->GetHWnd()))
276     {
277         /*
278          * alignment argument of multifont label is referred to in
279          * WmDrawItem method
280          */
281 
282         VERIFY(::InvalidateRect(l->GetHWnd(), NULL, TRUE));
283     }
284 ret:
285     env->DeleteGlobalRef(self);
286 
287     delete sas;
288 }
289 
_LazyPaint(void * param)290 void AwtLabel::_LazyPaint(void *param)
291 {
292     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
293 
294     jobject self = (jobject)param;
295 
296     AwtLabel *l = NULL;
297 
298     PDATA pData;
299     JNI_CHECK_PEER_GOTO(self, ret);
300     l = (AwtLabel *)pData;
301     if (::IsWindow(l->GetHWnd()))
302     {
303         l->LazyPaint();
304     }
305 ret:
306     env->DeleteGlobalRef(self);
307 }
308 
309 
310 /************************************************************************
311  * Label native methods
312  */
313 
314 extern "C" {
315 
316 JNIEXPORT void JNICALL
Java_java_awt_Label_initIDs(JNIEnv * env,jclass cls)317 Java_java_awt_Label_initIDs(JNIEnv *env, jclass cls)
318 {
319     TRY;
320 
321     /* init field ids */
322     AwtLabel::textID = env->GetFieldID(cls, "text", "Ljava/lang/String;");
323     DASSERT(AwtLabel::textID != NULL);
324     CHECK_NULL(AwtLabel::textID);
325 
326     AwtLabel::alignmentID = env->GetFieldID(cls, "alignment", "I");
327     DASSERT(AwtLabel::alignmentID != NULL);
328     CHECK_NULL(AwtLabel::alignmentID);
329 
330     CATCH_BAD_ALLOC;
331 }
332 
333 } /* extern "C" */
334 
335 
336 /************************************************************************
337  * WLabelPeer native methods
338  */
339 
340 extern "C" {
341 
342 /*
343  * Class:     sun_awt_windows_WLabelPeer
344  * Method:    setText
345  * Signature: (Ljava/lang/String;)V
346  */
347 JNIEXPORT void JNICALL
Java_sun_awt_windows_WLabelPeer_setText(JNIEnv * env,jobject self,jstring text)348 Java_sun_awt_windows_WLabelPeer_setText(JNIEnv *env, jobject self,
349                                         jstring text)
350 {
351     TRY;
352 
353     SetTextStruct *sts = new SetTextStruct;
354     sts->label = env->NewGlobalRef(self);
355     sts->text = (jstring)env->NewGlobalRef(text);
356 
357     AwtToolkit::GetInstance().SyncCall(AwtLabel::_SetText, sts);
358     // global refs and sts are deleted in _SetText()
359 
360     CATCH_BAD_ALLOC;
361 }
362 
363 /*
364  * Class:     sun_awt_windows_WLabelPeer
365  * Method:    setAlignment
366  * Signature: (I)V
367  */
368 JNIEXPORT void JNICALL
Java_sun_awt_windows_WLabelPeer_setAlignment(JNIEnv * env,jobject self,jint alignment)369 Java_sun_awt_windows_WLabelPeer_setAlignment(JNIEnv *env, jobject self,
370                                              jint alignment)
371 {
372     TRY;
373 
374     SetAlignmentStruct *sas = new SetAlignmentStruct;
375     sas->label = env->NewGlobalRef(self);
376     sas->alignment = alignment;
377 
378     AwtToolkit::GetInstance().SyncCall(AwtLabel::_SetAlignment, sas);
379     // global ref and sas are deleted in _SetAlignment
380 
381     CATCH_BAD_ALLOC;
382 }
383 
384 /*
385  * Class:     sun_awt_windows_WLabelPeer
386  * Method:    create
387  * Signature: (Lsun/awt/windows/WComponentPeer;)V
388  */
389 JNIEXPORT void JNICALL
Java_sun_awt_windows_WLabelPeer_create(JNIEnv * env,jobject self,jobject parent)390 Java_sun_awt_windows_WLabelPeer_create(JNIEnv *env, jobject self,
391                                        jobject parent)
392 {
393     TRY;
394 
395     AwtToolkit::CreateComponent(self, parent,
396                                 (AwtToolkit::ComponentFactory)
397                                 AwtLabel::Create);
398 
399     CATCH_BAD_ALLOC;
400 }
401 
402 /*
403  * Class:     sun_awt_windows_WLabelPeer
404  * Method:    lazyPaint
405  * Signature: ()V
406  */
407 JNIEXPORT void JNICALL
Java_sun_awt_windows_WLabelPeer_lazyPaint(JNIEnv * env,jobject self)408 Java_sun_awt_windows_WLabelPeer_lazyPaint(JNIEnv *env, jobject self)
409 {
410     TRY;
411 
412     jobject selfGlobalRef = env->NewGlobalRef(self);
413 
414     AwtToolkit::GetInstance().SyncCall(AwtLabel::_LazyPaint, (void *)selfGlobalRef);
415     // selfGlobalRef is deleted in _LazyPaint
416 
417     CATCH_BAD_ALLOC;
418 }
419 
420 } /* export "C" */
421