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
36struct SetTextStruct {
37    jobject label;
38    jstring text;
39};
40// Struct for _SetAlignment() method
41struct SetAlignmentStruct {
42    jobject label;
43    jint alignment;
44};
45/************************************************************************
46 * AwtLabel fields
47 */
48
49jfieldID AwtLabel::textID;
50jfieldID AwtLabel::alignmentID;
51
52
53/************************************************************************
54 * AwtLabel methods
55 */
56
57AwtLabel::AwtLabel() {
58    m_needPaint = FALSE;
59}
60
61LPCTSTR AwtLabel::GetClassName() {
62    return TEXT("SunAwtLabel");
63}
64
65/* Create a new AwtLabel object and window. */
66AwtLabel* 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        JNI_CHECK_NULL_GOTO(awtParent, "awtParent", done);
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
113done:
114    env->DeleteLocalRef(target);
115    return awtLabel;
116}
117
118void 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
174void AwtLabel::LazyPaint()
175{
176    if (m_callbacksEnabled && m_needPaint ) {
177        ::InvalidateRect(GetHWnd(), NULL, TRUE);
178        m_needPaint = FALSE;
179    }
180}
181
182void 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
194MsgRouting 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
204MsgRouting 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
225MsgRouting 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
237void 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    }
255ret:
256    env->DeleteGlobalRef(self);
257    env->DeleteGlobalRef(text);
258
259    delete sts;
260}
261
262void 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    }
284ret:
285    env->DeleteGlobalRef(self);
286
287    delete sas;
288}
289
290void 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    }
305ret:
306    env->DeleteGlobalRef(self);
307}
308
309
310/************************************************************************
311 * Label native methods
312 */
313
314extern "C" {
315
316JNIEXPORT void JNICALL
317Java_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
340extern "C" {
341
342/*
343 * Class:     sun_awt_windows_WLabelPeer
344 * Method:    setText
345 * Signature: (Ljava/lang/String;)V
346 */
347JNIEXPORT void JNICALL
348Java_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 */
368JNIEXPORT void JNICALL
369Java_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 */
389JNIEXPORT void JNICALL
390Java_sun_awt_windows_WLabelPeer_create(JNIEnv *env, jobject self,
391                                       jobject parent)
392{
393    TRY;
394
395    PDATA pData;
396    JNI_CHECK_PEER_RETURN(parent);
397    AwtToolkit::CreateComponent(self, parent,
398                                (AwtToolkit::ComponentFactory)
399                                AwtLabel::Create);
400    JNI_CHECK_PEER_CREATION_RETURN(self);
401
402    CATCH_BAD_ALLOC;
403}
404
405/*
406 * Class:     sun_awt_windows_WLabelPeer
407 * Method:    lazyPaint
408 * Signature: ()V
409 */
410JNIEXPORT void JNICALL
411Java_sun_awt_windows_WLabelPeer_lazyPaint(JNIEnv *env, jobject self)
412{
413    TRY;
414
415    jobject selfGlobalRef = env->NewGlobalRef(self);
416
417    AwtToolkit::GetInstance().SyncCall(AwtLabel::_LazyPaint, (void *)selfGlobalRef);
418    // selfGlobalRef is deleted in _LazyPaint
419
420    CATCH_BAD_ALLOC;
421}
422
423} /* export "C" */
424