GTK: Using an Offscreen Window to investigate the rendered dimensions of widgets - gtk

I am utilizing a Gtk.Offscreen_Window to investigate the heights of various off-screen widgets in order to figure out where to place them on-screen based on their height. I managed to accomplish this with the following pseudo code.
procedure My_Proc
is
use Gtk.Offscreen_Window;
use Gtk.Box;
Offscreen : Gtk_Offscreen_Window := Gtk_Offscreen_Window_New;
Box : Gtk_Box := Gtk_Box_New ( Orientation_Vertical );
begin
Offscreen.Set_Default_Geometry ( 1000, 1000 );
Offscreen.Add ( Box );
Offscreen.Show_All;
Ada.Text_IO.Put_Line( Glib.Gint'Image ( Box.Get_Allocated_Height ));
end My_Proc;
This code will correctly tell me the height of Box. Note that my original code is a bit more complex than this but I've simplified it for the sake of this posting.
The problem here has to do with Offscreen.Show_All procedure. I know that this is not correct practice with an Offscreen widget since it cannot be shown like a normal Window. This is further emphasized by a warning that shows up on the console when this code is executed:
(main:26724): Gdk-WARNING **: /build/buildd/gtk+3.0-3.10.8/./gdk/x11/gdkwindow-x11.c:5531 drawable is not a native X11 window
Without including the Show_All function the size calculations will be incorrect (returns 1), so the Show_All function seems to be doing something important albeit a little too much. I believe the solution is as simple as finding out what runs the allocation calculations within the Show_All function and running that directly. Unfortunately I don't know what that function is.
So the bottom line is: How do I correctly instruct the Offscreen_Window widget to perform its sizing calculations without using the Show_All function?
Thank you.
I am using Ada 2012, GtkAda (latest since mid 2015), Linux Kubuntu 14.04 but also expect this to run in Windows 7/8.

I've recently learned that using the Gtk.Widget.Size_Request function was more correct for my situation than using Gtk.Widget.Get_Allocated_Height to find out the height of my newly spawned widget. Using this eliminates the erroneous use of Gtk.Widget.Show_All all together.
Thank you again for all your help.

Related

Why is my "waterproof" polyhedron causing "WARNING: Object may not be a valid 2-manifold and may need repair!"?

In the script
difference() {
polyhedron(
points=[[0,0,0],
[2,0,0],
[2,1,0],
[0,1,0],
[0,0,2],
[0,1,2]],
faces=[[0,1,2,3],
[5,4,1,2],
[5,4,0,3],
[0,1,4],
[2,3,5]]);
cube([1,1,1]);
};
the polyhedron alone works fine (is rendered without warnings), but adding the cube above causes the warning WARNING: Object may not be a valid 2-manifold and may need repair! to be logged and the output to only render some parts of some surfaces.
I'm using OpenSCAD 2015.03-1 on Ubuntu 16.04.
This is because your polyhedron has some faces pointing into the wrong direction, causing issues when calculating the difference().
See the Manual and FAQ for details.
Changing the winding order of the affected polygons fixes the polyhedron:
difference() {
polyhedron(
points=[[0,0,0],
[2,0,0],
[2,1,0],
[0,1,0],
[0,0,2],
[0,1,2]],
faces=[[0,1,2,3],
[2,1,4,5],
[5,4,0,3],
[0,4,1],
[2,5,3]]);
cube([1,1,1]);
};
The difference is still non-manifold as cutting the cube results in 2 prism shaped objects just touching at one edge. That's also by definition not 2-manifold, so the warning remains.
Depending on how the exported model is supposed to be used, you could choose to ignore this warning and hope the tool processing the 3d model can handle that.
To remove the issue, for example the cube could be made a bit smaller like cube([1, 1, 0.999]).
An unrelated, but still useful strategy for preventing issues later on is to always make the cutting object a bit larger to ensure that no very thin planes remain, e.g. use cube([2,3,1.999], center = true). That will also remove the display artifacts in preview mode.

Fixed blocks in simulink diagram

Is there any solution for fixing a block in simulink diagram, to disable moving/resizing for the block ?
Is there any solution to draw kind of a shape in simulink (empty rectangles) ?
my aim is to fix an area in the model, so that the user is not allowed to design the model outside this area.
I tried using the callback functions with no success.
Thanks for any help.
As far as I know there is just a compromise.
As mentioned in the other answer you need to create a subsystem. In the block parameters you can set ReadOnly, so everything is fixed and greyed out, as you desired, or NoReadOrWrite access, so it is completely blocked. This solution works just for "naive" users as they can still change the properties to get access again. Maybe you find a way to prevent the user from entering the properties menu.
The secure way is much more complicated: protected Models
Regarding your question about the rectangular shape: I tried to find a solution for a long time and I'd say there is no way to "draw" something, though the backround is actually called "canvas" ;)
To your other comment: what is wrong about a subsystem? You can just block everything except the block you want the user to play around with. It opens in a new tab/window and it doesn't matter how big is everything. What you want is probably not possible in that manner.
You can achieve that to some extent using callback functions. For example let's have LoadFcn as:
A=get_param(gcb, 'Position');
and MoveFcn as
try
set_param(gcb, 'Position', A);
catch
end
This will prohibit moving and resizing, but not cut or delete. Obviously, this will pollute the workspace so you need to think of a way to manage that. If you want this for many blocks you can add the position to the userData property of block currBlock by
set_param(currBlock, 'UserData', get_param(currBlock, 'Position'));
and then just add this to the block's MoveFcn callback
try
set_param(gcb, 'Position', get_param(gcb, 'UserData'));
catch
end
You can even do this programmatically
moveFcn = sprintf([...
'try\n' ...
' set_param(gcb, ''Position'', get_param(gcb, ''UserData''));\n' ...
'catch\n' ...
'end\n']);
set_param(currBlock, ...
'UserData', get_param(currBlock, 'Position'), ...
'MoveFcn', moveFcn);
Did you tried using blocks? See this example: http://blogs.mathworks.com/seth/2008/07/27/how-to-make-your-own-simulink-block/

Delphi - TEdit Labels are not displaying (Windows 7/Vista only)

I we got few TEdit forms inserted on another form, but their labels are not displaying until I change size of the window. This happens just on Windows Vista / Windows 7. Windows XP has everything labeled correctly.
Ive already tested repaint / refresh (just TEdit / all form etc.) with no result.
Delphi 7.
Thank you for your answer
bad version
Correct version
code will be added soon enough :)
May be it is ALT Key press causes controls to disappear under Themes in Vista and XP bug?
I was able to mostly resolve this same problem on my project. It seems to be a painting order problem. The solution ultimately was to call frame.Refresh; on the frame that was not displaying properly. But, figuring out the right place to put that Refresh was a little tricky, I tried several places before I found a spot that worked. Where it worked for me was, in the method where I choose which nested frame to show on the options panel, and physically display the nested frame, to call frame.Refresh; on the inner-most frame surrounding the labels that are not drawing properly. Calling refresh on the inner frame rather than the frame for the entire window seemed to be key.
From the screen-shots you are showing, you look like you probably have a similar complex setup of frames where there are likely to be frames displayed on top of frames, which may change dynamically after the frame is displayed initially. That seemed to be the setup that would create the problem in the first place, the initially shown frame never seemed to have problems.
One note, however, is if the window moves off the screen or is re-sized, another window is dragged in front of it, or mouse-over buttons that are disappearing is that these actions could cause the problem to re-appear spontaneously. There may be additional places, such as in a special handler for window resize, etc. or on a timer where you to call refresh on the frame periodically, similar to some of the solutions mentioned for the ALT Key bug. There seems to be some overlap in the type of problem and how to fix it but does not the exact same cause (this bug seems to happen regardless of the Alt key)
There are bugs in TButton when running with windows Themes.
You can search 'ThemesEnabled' in StdCtrls.pas, remove/comment all its related branch, like this:
procedure TButton.CNCtlColorBtn(var Message: TWMCtlColorBtn);
begin
with ThemeServices do
{
if ThemesEnabled then
begin
DrawParentBackground(Handle, Message.ChildDC, nil, False);
// Return an empty brush to prevent Windows from overpainting we just have created.
Message.Result := GetStockObject(NULL_BRUSH);
end
else
}
inherited;
end;
Then compile it, and replaced lib/StdCtrls.dcu with your patched version.
{ Labels no Windows Vista, 7, 8 to Fix the problem, Delphi 7 32 bits }
on FormShow:
var
i : Integer;
begin
For i := 0 to (Form1.ComponentCount - 1) do
begin
If (Form1.Components[i].ClassType = TLabel) then
TLabel(Form1.Components[i]).Refresh;
end;
end;
Just run this.
I'm getting the same thing, except it only seems to be a problem while the application is themed. If it is unthemed (ie Project->Options->Application->Appearance->Default Style = Windows) it works fine, no refresh or repaint needed.
Seems to be related specifically to the TFrame class so I wonder if something about the redraw handler isn't amok (related to Invalidate). Something in the ChangeNotify process or the Windows message pump in the VCL might not making its way up the parent control chain and responding with a cascading repaint funnelling back down on everything "invalidated".
One other cludge I did try with success was setting the host control Visible property to False on one line and then to true in the next line ie:
procedure TFrame1.UpdatePanel;
Panel1.Visible := False;
Panel1.Visible := True;
end;
Then calling this method where the proper drawing is needed.
All of the other child controls of Panel1 were drawn perfectly. You might have to cache the location of the text cursor if your update occurs while modifying the contents of one of the child controls like a TEdit or TMemo. This should be trivial compared to hours of hunting down the cause of the problem. Maybe looking into the VCL source of the Setter method for the Visible property on the offending control host (such as the TPanel) might provide some insight to the overall problem of why Repaint and Refresh don't seem to work as they should in this case.
Actually it is much simpler than any of the solutions presented so far.
The only thing needed is to respond to the WM_UPDATEUISTATE message.
Add a procedure like the one bellow to the form:
...
protected
procedure WmUpdateUIState(var Msg: TMessage); message WM_UPDATEUISTATE;
...
procedure TForm1.WmUpdateUIState(var Msg: TMessage);
begin
inherited;
Invalidate;
end; { WmUpdateUIState }
Done!
Tested on Windows 10 64 bits.
One can speed things up by creating a unit like this:
unit FixAltKeyForm;
interface
uses
Windows, Messages, Classes, Forms;
type
TForm = class(Forms.TForm)
protected
procedure WmUpdateUIState(var Msg: TMessage); message WM_UPDATEUISTATE;
end; { TForm }
implementation
{ TForm }
procedure TForm.WmUpdateUIState(var Msg: TMessage);
begin
inherited;
Invalidate;
end; { WmUpdateUIState }
end.
Add the unit's name to the uses clause of the interface session of any form where this behavior is wanted and you are done. Only be sure to put the unit's name AFTER 'Forms' in the uses clause. No need to create a package nor to install anything at all. That's what I call Visual Subclassing, for lack of a better term.

Disable form rising to the top

I want a form that when I set at the bottom of the z-order it stays there. I tried:
SetWindowPos(Handle,HWND_BOTTOM,Left,Top,Width,Height,SWP_NOZORDER);
and when I overlap it with some other apps it stays at the bottom as I need. However when I click on it, it rises to the top. I then tried:
SetWindowPos(Handle, HWND_BOTTOM, Left, Top, Width, Height,
SWP_NOACTIVATE or SWP_NOZORDER);
and various other switches from this website...
http://msdn.microsoft.com/en-us/library/ms633545.aspx
But it still rises to the top.
SetWindowPos sets the position of a window only when it is called, it does not establish a state. Handling WM_WINDOWPOSCHANGING is the correct way to do this:
While this message is being processed, modifying any of the values in
WINDOWPOS affects the window's new size, position, or place in the Z
order. An application can prevent changes to the window by setting or
clearing the appropriate bits in the flags member of WINDOWPOS.
type
TForm1 = class(TForm)
..
private
procedure WindowPosChanging(var Msg: TWMWindowPosMsg);
message WM_WINDOWPOSCHANGING;
end;
..
procedure TForm1.WindowPosChanging(var Msg: TWMWindowPosMsg);
begin
if Msg.WindowPos.flags and SWP_NOZORDER = 0 then
Msg.WindowPos.hwndInsertAfter := HWND_BOTTOM;
inherited;
end;
Never tried it, but you might get somewhere trapping the message WM_WINDOWPOSCHANGING, and twiddling with Z order. Could get complicated though and I personally would find it irritatingly non-standard.
A menu option equivalent to cacsade but with a z-order sort might be a better option, I mean if they clicked on it they expect to see it.
Out of instinct, I wouldn't trust that the app will always work as you expect. Other applications may have a much more strict method of forcefully bringing its self in front of yours, or vice-versa in your case, sending it to the back. For example, a timer which repeatedly sends the window to the back. Then if you have two of such apps layered, you would watch them fight each other, basically flickering back and forth. In the end, I wouldn't count on a permanent 100% solution for this because you never know what other applications might do to override yours.

Turning on anti-aliasing in SWT

I've called gc.setAntialias(SWT.ON); and it does nothing. According to that method, it should work.
The Javadoc states:
Sets the receiver's anti-aliasing
value to the parameter, which must be
one of SWT.DEFAULT, SWT.OFF or SWT.ON.
It's not working for me, and I'm painting on a simple Canvas.
The following worked for me in an app I built and my guesses at when/how you have to do this.
So I created a new GC, set the Antialias as you did and then drew what I needed to with that gc object. The key is attaching it to the shell you will draw in.
GC gc = new GC(shell);
gc.setAntialias(SWT.ON);
//then I attach to LightweightSystem for testing.
LightweightSystem lws = new LightweightSystem(shell);
Other than that make sure you do this before you draw anything. If you have to call it afterwards maybe try calling a repaint or redraw of the entire space.
Sorry without more information I am not sure exactly what is wrong.
Following derBiggi's answer, you ca also force the advanced option to true.
gc.setAdvanced(true)
Also, if you're drawing labels, make sure you use gc.setTextAntialias( SWT.ON );
You can also check if gc.getAdvanced() returns true, it should after setAntialias() or setTextAntialias was set.
Besides from that it's pretty straight forward.