Project

General

Profile

p.patch

Paula Păstrăguș, 01/27/2026 09:56 AM

Download (7.87 KB)

View differences:

new/src/com/goldencode/p2j/ui/client/gui/GuiButton.java 2026-01-27 14:38:53 +0000
20 20
** 009 IMS 20250704 The mouseOver modifier has been changed from private to protected. Rfs:#9973.
21 21
** 010 EVL 20260105 Improved bounds check for mouseExited event to avoid regressions.  We need to check if
22 22
**                  the mouse point is inside possible tooltip overlay window that can overlap the button.
23
**     PMP 20260127 TODO
23 24
*/
24 25

  
25 26
/*
......
85 86
import com.goldencode.p2j.ui.client.widget.Container;
86 87

  
87 88
import java.awt.event.*;
88
import java.util.concurrent.*;
89 89
import java.util.logging.*;
90 90

  
91 91
/**
......
109 109
   /** The mouse is dragging */
110 110
   private boolean mouseDragging;
111 111
   
112
   /** TODO */
113
   private Runnable repaintListener = null;
114
   
115
   /** TODO */
116
   private boolean suppressNextEnterRepaint = false;
117

  
112 118
   /**
113 119
    * This constructor creates a button with a given text label.
114 120
    *
......
151 157
   }
152 158
   
153 159
   /**
160
    * TODO 
161
    * 
162
    * @param   listener
163
    *          TODO
164
    */
165
   public void setRepaintListener(Runnable listener)
166
   {
167
      repaintListener = listener;
168
   }
169
   
170
   /**
171
    * TODO
172
    */
173
   public void runRepaintListener()
174
   {
175
      if (repaintListener != null)
176
      {
177
         repaintListener.run();
178
      }
179
      
180
      clearRepaintListener();
181
      clearHoverSuppression();
182
   }
183
   
184
   /**
185
    * TODO
186
    */
187
   public void clearHoverSuppression()
188
   {
189
      suppressNextEnterRepaint = false;
190
   }
191
   
192
   public void clearRepaintListener()
193
   {
194
      repaintListener = null;
195
   }
196
   
197
   /**
154 198
    * Process the notification of a mouse enter event occurred for this widget. Store the new 
155 199
    * state and call repaint to update the button's visual.
156 200
    *
......
163 207
      if (isEnabled())
164 208
      {
165 209
         this.mouseOver = true;
166
         if (ThemeManager.getCurrentTheme().isMouseHoverSensitive())
210
         // TODO: 
211
         if (ThemeManager.getCurrentTheme().isMouseHoverSensitive() && !suppressNextEnterRepaint)
167 212
         {
168 213
            repaint();
169 214
         }
215
         clearHoverSuppression();
170 216
      }
171 217
   }
172 218
   
......
187 233
      
188 234
      final int xMouse = e.getXOnScreen();
189 235
      final int yMouse = e.getYOnScreen();
190
      
191
      processMouseExited(xMouse, yMouse);
236
            
237
      // for certain cases we need to check if we are still inside the button
238
      NativePoint p = this.displayPhysicalLocation();
239
      CoordinatesConversion cc = screen().coordinates();
240
      NativeRectangle rect = cc.rectangleToNative(this.bounds());
241

  
242
      final ToolTip tt = ToolTip.getInstance();
243
      // only for buttons with tooltips
244
      boolean skipBtnRepaint = xMouse >= p.x && xMouse <= p.x + rect.right() - rect.left() &&
245
                               yMouse >= p.y && yMouse <= p.y + rect.bottom() - rect.top() &&
246
                               tt != null && tt.isClockActive() && tt.isInsideTooltipArea(xMouse, yMouse);
247
                               
248
      if (ThemeManager.getCurrentTheme().isMouseHoverSensitive() && skipBtnRepaint)
249
      {
250
         clearRepaintListener();
251
         setRepaintListener(() -> repaint());
252
         suppressNextEnterRepaint = true;
253
         return;
254
      }
255
                               
256
       // normal exit
257
       if (ThemeManager.getCurrentTheme().isMouseHoverSensitive())
258
       {
259
          repaint();
260
       }
261
       
262
       clearRepaintListener();
263
       clearHoverSuppression();
192 264
   }
193 265
   
194 266
   /**
......
248 320
               repaint();
249 321
            }
250 322
         }
323
         
251 324
      }
252 325
   }   
253 326
   
......
332 405
         MouseEvent.MOUSE_DRAGGED,
333 406
      };
334 407
   }
335

  
336
   /**
337
    * The actual mouse exit event handler.  Can recall itself with forwarding the code to event loop.
338
    *
339
    * @param   xMouse
340
    *          The mouse X absolute position.
341
    * @param   yMouse
342
    *          The mouse Y absolute position.
343
    */
344
   private void processMouseExited(int xMouse, int yMouse)
345
   {
346
      // in this case we re-enter mouse over button
347
      if (this.mouseOver)
348
      {
349
         return;
350
      }
351
      
352
      // for certain cases we need to check if we are still inside the button
353
      NativePoint p = this.displayPhysicalLocation();
354
      CoordinatesConversion cc = screen().coordinates();
355
      NativeRectangle rect = cc.rectangleToNative(this.bounds());
356

  
357
      final ToolTip tt = ToolTip.getInstance();
358
      // only for buttons with tooltips
359
      boolean skipBtnRepaint = xMouse >= p.x && xMouse <= p.x + rect.right() - rect.left() &&
360
                               yMouse >= p.y && yMouse <= p.y + rect.bottom() - rect.top() &&
361
                               tt != null && tt.isClockActive() && tt.isInsideTooltipArea(xMouse, yMouse);
362

  
363
      // If the event occurs within the button bounds, the hover state should be maintained. 
364
      // this can happen for big enough button and currently active tooltip
365
      if (ThemeManager.getCurrentTheme().isMouseHoverSensitive())
366
      {
367
         if (skipBtnRepaint)
368
         {
369
            // we have to repeat mouse exit handler until the mouse will become outside the button area
370
            ThinClient tc = ThinClient.getInstance();
371
            tc.invokeLaterOS(() ->
372
            {
373
               tc.eventDrawingBracket(this, () ->
374
               {
375
                  NativePoint np = tc.getMousePosition();
376
                  processMouseExited(np.x, np.y);
377
               });
378
            }, 250L, TimeUnit.MILLISECONDS);
379
         }
380
         else
381
         {
382
            // immediate repaint
383
            this.repaint();
384
         }
385
      }
386
   }   
387 408
}
new/src/com/goldencode/p2j/ui/client/gui/ToolTip.java 2026-01-27 14:05:25 +0000
41 41
** 015 AB2 20250613 Added support for interpreting the accelerator symbol ('&'). See #10125.
42 42
** 016 PMP 20250723 Do not activate the tooltip if a pop up menu is displayed. See #10233.
43 43
** 017 EVL 20250112 Adding method to check if the given absolute point is inside tooltip overlay.
44
**     PMP 20260127 TODO
44 45
*/
45 46

  
46 47
/*
......
163 164
   /** Last activation mouse event absolute Y, otherwise undefined. */
164 165
   private int yAbs;
165 166
   
167
   /** TODO */
168
   private Widget<?> host;
169
   
166 170
   /**
167 171
    * This constructor is private since the class is a singleton.
168 172
    */
......
321 325
      // the absolute mouse position is also required
322 326
      this.xAbs = evt.getXOnScreen();
323 327
      this.yAbs = evt.getYOnScreen();
328
      this.host = widget;
324 329
      
325 330
      clock = new TooltipWorker((AbstractWidget<?>) widget, text);
326 331
   }
......
343 348
         overlayWindow = null;
344 349
      }
345 350
      
351
      if (host != null && host instanceof GuiButton)
352
      {
353
         NativePoint p = host.displayPhysicalLocation();
354
         CoordinatesConversion cc = screen().coordinates();
355
         NativeRectangle rect = cc.rectangleToNative(host.bounds());
356
         
357
         boolean inHostBounds = xAbs >= p.x                              && 
358
                                xAbs <= p.x + rect.right() - rect.left() &&
359
                                yAbs >= p.y                              && 
360
                                yAbs <= p.y + rect.bottom() - rect.top();
361
         
362
         // check if the mouse position is outside of the button boundaries
363
         if (!inHostBounds)
364
         {
365
            ((GuiButton) host).runRepaintListener();
366
         }
367
         else
368
         {
369
            ((GuiButton) host).clearRepaintListener();
370
            ((GuiButton) host).clearHoverSuppression();
371
         }   
372
      }
373
      host = null;
346 374
      ThinClient.getInstance().registry().removeWidget(this.getId());
347 375
   }
348 376