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 
  57 AwtLabel::AwtLabel() {
  58     m_needPaint = FALSE;
  59 }
  60 
  61 LPCTSTR AwtLabel::GetClassName() {
  62     return TEXT("SunAwtLabel");
  63 }
  64 
  65 /* Create a new AwtLabel object and window. */
  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 
 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 
 174 void AwtLabel::LazyPaint()
 175 {
 176     if (m_callbacksEnabled && m_needPaint ) {
 177         ::InvalidateRect(GetHWnd(), NULL, TRUE);
 178         m_needPaint = FALSE;
 179     }
 180 }
 181 
 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 
 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 
 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 
 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 
 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 
 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 
 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
 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
 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
 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
 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
 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" */