FLTK logo

STR #3385

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 Home  |  Articles & FAQs  |  Bugs & Features  |  Documentation  |  Download  |  Screenshots  ]
 

Return to Bugs & Features | SVN ⇄ GIT ]

STR #3385

Application:FLTK Library
Status:1 - Closed w/Resolution
Priority:1 - Request for Enhancement, e.g. asking for a feature
Scope:3 - Applies to all machines and operating systems
Subsystem:Core Library
Summary:Introduce new classes Fl_Rect and Fl_Rect2
Version:1.4-feature
Created By:AlbrechtS
Assigned To:AlbrechtS
Fix Version:1.4.0 (SVN: v12302)
Update Notification:

Receive EMails Don't Receive EMails

Trouble Report Files:


Name/Time/Date Filename/Size  
 
#1 AlbrechtS
11:05 May 31, 2017
rect.cxx
5k
 
 
#2 AlbrechtS
11:12 May 31, 2017
Fl_Rect.H
4k
 
 
#3 manolo
01:59 Jun 12, 2017
group_bounds.patch
8k
 
 
#4 AlbrechtS
09:34 Jun 13, 2017
group_bounds_v2.patch
11k
 
 
#5 AlbrechtS
08:44 Jun 21, 2017
group_bounds_v3.patch
16k
 
     

Trouble Report Comments:


Name/Time/Date Text  
 
#1 AlbrechtS
10:57 May 31, 2017
I propose to add one or two new classes to FLTK:

(1) class Fl_Rect
(2) class Fl_Rect2 (less important).

Class Fl_Rect may be used for overloaded widget constructors and other overloaded methods like fl_measure(), fl_text_extents(), fl_rect(), fl_rectf(), and maybe more internal functions. There are many internal functions that could be simplified if only one struct was passed instead of four arguments (X, Y, W, H). See also documentation in attached file Fl_Rect.H (not yet ready).

Fl_Rect.H may be incomplete and contains class Fl_Rect2 as well which may be considered optional (see below).

Class Fl_Rect2 (its name may be changed, I didn't find a better one) describes the layout of the internal sizes() array of Fl_Group. The protected method sizes() returns a currently undocumented array of int's (int*) that describes the stored sizes of the Fl_Group widget itself, its resizable() widget, and of all children. Since derived classes can access this array it should IMHO be documented. I propose to create new methods to access the stored array in a documented way for developers of derived classes. Currently it is possible to cast the returned array (int*) to an Fl_Rect2* and access the array through this pointer as done in the attached demo program rect.cxx. I believe that this is standard conformant, although there are alignment questions to deal with.

Class Fl_Rect contains x, y, w, h (standard FLTK coordinates and sizes).

Class Fl_Rect2 (unfortunately; as defined by Fl_Group) contains left, right, top, and bottom coordinates (in this order). I suggest not to change this order and contents for backwards compatibility (derived classes), but we can use Fl_Rect2 for accessor methods and documentation.
 
 
#2 AlbrechtS
11:05 May 31, 2017
Attached file rect.cxx can be used to test the proposed classes and access to the stored sizes() array using class Fl_Rect2.

Two classes MyWindow and MyButton show overloaded constructors that use class Fl_Rect to simplify argument lists. This is just for convenience, but such overloaded constructors might also be added to the FLTK core widgets.

Instructions:

 (1) save Fl_Rect.H as FL/Fl_Rect.H in your FLTK working directory
 (2) `fltk-config --compile rect.cxx'
 (3) ./rect

The class implementation is entirely contained in FL/Fl_Rect.H (this may be changed later).
 
 
#3 AlbrechtS
11:22 May 31, 2017
Please see also discussion in fltk.coredev, thread "Introduce new classes Fl_Rect and Fl_Rect2", opened today (2017-05-31), and vote. Thanks.  
 
#4 manolo
02:04 Jun 12, 2017
About improving the int* Fl_Group::sizes() member function:

an approach would be to define a new, preferred, API
   Fl_Rect* Fl_Group::bounds()
that would be used by FLTK internally, that is, in
Fl_Group.cxx and Fl_Tile.cxx

and to maintain int* Fl_Group::sizes() just for
backward compatibility with putative existing source code.

This is implemented in attached group_bounds.patch
 
 
#5 AlbrechtS
05:01 Jun 12, 2017
Thanks for the comment and the patch.

Re #4: I'd really like to do it with this new internal Fl_Rect array instead of the int array used by sizes(). Code readability would be improved, and some of the code would also be shorter. I had already implemented a similar patch for Fl_Tile with the new bounds() method.

Unfortunately the patch, as given, would change the API in a way that would open memory leaks in existing programs that are just recompiled for new FLTK versions (1.4) because they won't know of the necessary delete[] after using sizes().

Programs "corrected" for FLTK 1.4 might even crash if recompiled for FLTK 1.3, unless the necessary delete[] operator would be guarded by FLTK version checks. The latter could be documented, so this wouldn't be a real issue.

A possible way out would be to _keep_ the sizes_ pointer additional to Fl_Rect *bounds_ in Fl_Group so we can control the deletion of the (old) sizes_ array as we do with bounds_, but that would increase Fl_Group's size by one pointer size, i.e. 4 or 8 bytes depending on the platform.

If we went this way we could deprecate sizes() and remove the method and the additional pointer in a later FLTK version. We could even remove the sizes() method and pointer with a configure/CMake option in FLTK 1.4 (not default, of course) for those that compile FLTK for their own use only. Linux distros would use the default and still have sizes() etc.

Question: should we also rename init_sizes() to init_bounds() for consistency and keep (add) init_sizes() as an alias for compatibility? Note that init_sizes() is public and certainly used frequently in existing code.

The longer I think about it, the more appealing this seems to be to me. If we'd vote I'd likely vote +1 for this approach.

Technical notes (just to not forget in case the patch would be used):

(1) The patch calls bounds() repeatedly in the new implementation of sizes(). I suggest to call bounds() only once and use bounds_ (or a local variable) later for optimization.

(2) The patch adds:
+    //Fl_Rect* p = bounds_ = new Fl_Rect[children_+2]; // this repeatedly calls the Fl_Rect constructor
+    Fl_Rect* p = bounds_ = (Fl_Rect*)new char[(children_+2)*sizeof(Fl_Rect)];

I'm not sure if the proposed 'new char[(children_+2)*sizeof(Fl_Rect)]' might potentially produce alignment issues. Admittedly, the default constructor would initialize four int's to zero, but I believe this is neglectible, so I'd rather suggest to use 'new Fl_Rect[children_+2]'.
 
 
#6 manolo
00:50 Jun 13, 2017
Re: int* Fl_Group::sizes()

Yes, I believe this partially undocumented member function
(because the content of the returned array was not documented)
could be deprecated, and removed in a later step.

This will oblige to keep two pointers in each Fl_Group object,
sizes_ and bounds_, to avoid memory leaks.

I see now there are 2 other calls to Fl_Group::sizes() in
Fl_Tile.cxx, which should be similarly converted to calls
to Fl_Group::bounds().

Re: how to construct an array of Fl_Rect objects
This statement
   Fl_Rect* p = bounds_ = new Fl_Rect[children_+2];
calls (children_+2) times the Fl_Rect constructor which sets each
object member variable to 0.
Defining two Fl_Rect constructors, with and without arguments
  Fl_Rect(int x, int y, int w, int h) : x_(x), y_(y), w_(w), h_(h) {}
  Fl_Rect() {}
may be the way to go.
 
 
#7 manolo
01:05 Jun 13, 2017
I had not seen the new FL/Fl_Rect.H file

My proposal for this constructor
   Fl_Rect() {}
is not possible. I agree that it's safer to construct
an array of Fl_Rect objects with new Fl_Rect[number]


I would suggest to remove the copy constructor for the following reason,
taken from http://www.cplusplus.com/articles/y8hv0pDG/  :

  When do I need to write a copy constructor?
  First, you should understand that if you do not declare a copy
  constructor, the compiler gives you one implicitly. The implicit
  copy constructor does a member-wise copy of the source object.

Thus, the implicit copy constructor is enough for Fl_Rect objects.
 
 
#8 AlbrechtS
03:43 Jun 13, 2017
Copy constructor removed as suggested (svn r12260).

I was working on a complete patch yesterday, but I did not yet post it here because it was not yet ready. I saw and fixed the other calls of Fl_Group::sizes() in Fl_Tile.cxx and made some more changes. This is a proposal based on your changes (Fl_Group::bounds()) and my comments.

I'll post the complete patch later today (I'm busy with something else right now), so please wait and don't waste your time updating your patch.
 
 
#9 AlbrechtS
09:34 Jun 13, 2017
Uploaded file group_bounds_v2.patch is my modified patch proposal (use patch -p1 with svn r12260 or later).

Changes:

 - both bounds_ and sizes_ variables, no need to delete[] array
   returned by sizes()
 - sizes() always delete[]'s the array and creates a new one [1]
 - Fl_Tile patch completed (all occurrences of sizes()
   replaced with bounds())
 - some minor other changes, e.g. replaced 'type()<FL_WINDOW'
   with '!as_window()' etc.

[1] Do we really need to delete[] sizes_ always if it is not NULL? Maybe we can do the same as we do with bounds_, i.e. don't allocate a new array if it exists, but I'm not sure. Needs code review to decide.

I tested the code with test/tile and it seems to work, but maybe we need more testing with 'old' code that uses sizes()...

Looking forward to your comments and test results...
 
 
#10 AlbrechtS
08:44 Jun 21, 2017
The new file group_bounds_v3.patch is (AFAICT) an update to the previous patch:

- use "better" Fl_Rect constructors in Fl_Group::bounds()
- do not delete[] sizes_ in sizes() if it is not NULL
- simplify some code
- complete documentation

This is tested well, even with old code that uses sizes() [1]. It is not necessary to delete[] the sizes_ array and recreated it if sizes() is called and the sizes_ array exists (sizes_ != NULL).

[1] I used the old version of Fl_Tile that used to call sizes() and work with the old int* array.
 
 
#11 AlbrechtS
08:46 Jun 21, 2017
Summary / Conclusion:

I propose to commit this update. It adds the method Fl_Group::bounds() and is otherwise backwards compatible: Fl_Group::sizes() is retained, but now deprecated. The new class Fl_Rect has already been committed previously.

The only drawback is that we need one additional pointer in Fl_Group until Fl_Group::sizes() can be removed (likely in 1.6.0 or higher). If requested we could add a configure/CMake option to remove Fl_Group::sizes() and the additional pointer as an ABI breaking feature for users that compile their own library version and want to save some address space.
 
 
#12 AlbrechtS
12:22 Jul 07, 2017
Fixed in Subversion repository.

Contrary to the title of this RFE only one new class (Fl_Rect) was added.
Fl_Rect2 or Fl_Bounds, as discussed, were not necessary.
 
     

Return to Bugs & Features ]

 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.