I'm currently writing a plugin for a GTK+ Software (Pidgin). I haven't worked with GTK before, so I'm only somewhat familiar with how objects work from the documentation.
I'm creating a few thousand buttons with images on them (smileys) and storing them in a doubly linked list. Then, on user request, a portion of these buttons is showed on a dialog, organized in hboxes and vboxes. As soon as the user closes the dialog, it gets destroyed and so do the hboxes, vboxes, buttons and images. But I don't want the buttons and its images to be destroyed since I'm trying to keep them in the doubly linked list to be able to quickly show them again.
What I tried:
Creating extra references to the buttons using g_object_ref() or g_object_ref_sink(). This did not change anything.
Connecting to a "delete" signal which is supposed to be called before finalization. This signal isn't emitted though.
Edit: I also checked the GObject.ref_count field, and it's not going to zero. So that's not the cause of the problem.
I'd be grateful for any hints on how to keep the buttons from being destroyed as efficiently as possible
Related
So I have looked through existing answers tagged with dockpanel-suite and have not found what I am looking for (as I type this, it is also not appearing in the Similar Questions area). For starters, note that I am NOT asking about saving and restoring the entire Workspace.
So here is the scenario. I have a graphical window (we will call it "Timeline") that is added upon user request. When it is added, it is automatically docked to the bottom-most area of the main form. The user then takes the Timeline window and redocks it somewhere else (could be docked to an edge, or within another docking pane) and changes its docking behavior (floating, auto-hide, tab, etc.).
A demonstrable example is in Visual Studio. If you have the Solution Explorer on a tab within an docked pane on the right and close Solution Explorer, you can go to View -> Solution Explorer and bring it back up again, and it restores to the correct location.
Now the user closes the Timeline window entirely by hitting the [x] on its pane, and in the future, they request to add it to the application again. I want to bring it back in the last dock state and position it was in when it was last closed.
Now, I appear to be able to catch the closing of the pane with the ContentRemoved event, but in there e.Content.DockHandler.Pane, e.Content.DockHandler.PanelPane and e.Content.DockHandler.FloatPane are all null so I have no obvious way to get the previous dock geometry. e.Content.DockHandler.DockPanel is valid, but it is the parent/root docking panel, and calling SaveAsXml(...) does nothing for me because it would get the entire workspace.
Even if I were able to capture it here, information I need. However, I do not appear to be able to simply call LoadFromXml(...) on anything either.
If I try to do it before the DockContent object is added to the DockPanel, DockHandler.DockPanel member is null, so I appear to have no place to restore the XML into, even if I was able to get it.
There are no other events hanging off of DockPanel that seem to be able to help me here.
So - is there a way to do this, and what is the correct way to do it? I want to make sure I am not barking up the wrong tree with trying to capture the dock information as XML when closed and restore it later.
I have toyed with the idea of not actually closing the window but just undocking and hiding it, but have not explored that very far yet. Same with hooking the DockChanged event, but it does not seem to fire on the DockContent objects being docked/floated/etc. and I am not sure why.
Also the solution needs to be robust enough so that I can correctly handle scenarios such as if the last docking parent no longer exists. For example, if it was docked as a tab somewhere, but now that parent window (containing the tabs) has also been closed. I do not know if LoadFromXml, presuming it is the right way to do, is robust enough to handle this scenario, as I have not been able to test it yet.
If I understand the question, what I do is to trap the Closing or FormClosing event, .Hide() the form and set e.Cancel = true. If you are using DockContent, then there is a HideOnClose() that does the work for you. Then when you want to "re-open" the window, you simply use an empty .Show(), and it will Show right where it was when you "closed" it.
As far as saving if the last docking parent no longer exists, I agree with Lex Li, that will take a hack.
I have a project that I'm working on that has a TreeView Control in it. For everything underneath Level 1, those nodes are being used as a bookmark function, so we want a Tri-State CheckBox there. I found a control that I'm using here.
However, as the top two levels in the TreeView do not need bookmarking, the customer wants an Image there. I found this page who's response gets CheckBoxes to disappear on specific Nodes. Unfortunately, the API calls clash with the ones used in the above Tri-State TreeView and they both can't work at the same time.
Basically, what I'm looking for is how to get Images in nodes on the top two levels, and Tri-State CheckBoxes on the lower levels. I'd be more than willing to try another Tri-State CheckBox if necessary.
Also, when the user clicks on the Image in the top two levels, the image shouldn't change. I found this page which does keep the image from changing, but removes the PlusMinus, Lines, and RootLines from the control.
Sorry in advance that this is such a ridiculous and specific request.
Ok, I finally got this figured out. Using the Tri-State Treeview Control, I am able to still have access to the AfterClick event on the Treeview.
I had added a series of Checkbox icons to the ImageList, and after determining which CheckState (of the 3) my underlying object was in. Then I set the ImageIndex, SelectedImageIndex, and StateImageIndex (probably don't need the last one, but I was being thorough) to the proper index of the ImageList.
I won't post any code for now, but if you are trying to do the same thing, let me know and I'll upload until it becomes clear.
I need to change the Background Image of my Application if user changes theme from "Light" to "Dark" or vice-vesa in code behind. I hope these should be done in Page Loded event
#TimDams pointed you to one of the nice ways to detect what-theme-is-now-set, but I didn't notice there any information how to detect a change to the theme during the application runtime. The user could start your app, then bump forward to the menu, change the theme, and get back to your app. While you may think that your app will be tombstoned and then restarted and renavigated to your page with full cycle with all pageloads -- it is not 100% true.
Firstly, the PageLoaded is NOT a good place to do the initial check-and-set-styles, because, if you get that event called, then the page, probably, has already rendered once. If I remember well, the PageLoaded is invoked just after the first render. If this is true, then you will have to detect the colors earlier, for example in the LayoutUpdated (warning: this event is a great spammer. I mean, it gets called gazillions times. Attach a single-shot handler, you know, such that will instantly unattach-self on first invocation). Maybe you will be able to do it in the Page's .ctor, just after InitializeComponent. Or in the OnApplyTemplate or MeasureOverride, or at least ArrangeOverride -- the visuals should be mostly/fully available there.
Buuuut. I've intentionally 'bolded-out' the word "initial". With Mango, there's some multitasking getting more and more common, but even the pre-Mango 7.0 version does not guarantee that your app will be tombstoned. From my observations in early 7.0, for example, starting the MediaPlayer from WebBrowser component does not tombstone your app:) If you have some time to read, check WP7 recover from Tombstone and return to page for details on the "pause" vs "tombstone".
Anyways, if your app gets "paused" and the user switches themes in the meantime, I think (I've NOT checked) that your page will (in most of the cases) be just temporarily hidden and upon returning to the screen, it will probably not be re-created and will not be re-(Page)Loaded. If it is true, then you will have not so easy problem to solve, because your app may be paused, the OS rethemed, and your app unpased virtually in any moment of time and the only events you will get in the mean time are .... global events of App.Deactivated and App.Activated. It is possible that completely none of per-page events will fire [but I've not checked - before you do anything I suggest below, CHECK IT].
If this pessimistic view is really true, than in those events, you will have to detect the current theme (->Tim's post), then somehow inform your current Page that themes changed - or not. If you have your ViewModel at least a bit separated from the rest of the app (as it should be:) ) you have an easy option to do it: create in that ViewModel a set of properties (dp or inotif) like Brush Background, Brush Foreground, Brush Hightlight, and other that you need, and instead of harcoding colours in your XAML - bind to those properties. You may event want to create a separate class for all those many Brushes and other Styles, let's say "pub class MyCurrentAppTheme" and keep that props there, and expose such object from ViewModel - whatever. Just Bind your colors to whatever -- but whatever that will be "logically global" and that will be easily accessible from the App.Acticated event handler. Having that done, in the App.Activated, detect the current theme and if changed, so through all the colors kept in VM and set them appropriatelly. Voil'a, whole your App gets recoloured properly.
But mind that still - there might be some transient blinks and flashes between the rendering of cached old theme, refreshing databound objects, and redrawing fresh theme. I hope not, but I sense it may occur, especially when returning from fast-switch tool (long back press): I think that the device captures the 'last screenshot' of your app in the backbuffer and uses that throughout all the time the app is 'minimalized' to do transitions animations, to show the fast-app-switch overview and so on.. again, I've not checked, but I doubt that during such animations the pagecontents are 'live', it could be very demaning on CPU/GPU resources. Any one knows anything on that? It could be a nice test to have some looping animation on the page and then to switch out and check in the fast-switch overview, whether the animation moves or is halted!:)
If your application is tombstoned, all your controls will be recreated and the new theme will be applied. If you'd like to manage your light/dark specific styles in a similar vein to normal themes, you might want to take a look at a custom ResourceDictionary I blogged about a while back.
Unfortunately, as of Mango there, is a bug (?) related to fast application switching that causes the theme to remain unchanged in your application. The bug is outlined in this question and its linked posts:
Is there a bug when changing themes when app is deactivated and reactivated in Windows Phone Mango
My ResourceDictionary is still useful for the initial startup but it appears, unfortunately, that nothing can be done to workaround the Mango bug.
For this no event exists. You need to figure this out manually by comparing the PhoneBackgroundBrush color to see if the user has the dark or light theme and compare it with your last stored value.
Were you able to do some test on the App.Activate - Deactivate?
I decided to use a different path to solve the issue of dynamic theme change.
I've assigned to all text and buttons only system resource colors.
For the icons inside the buttons in the window instead of using PNG images-icons I used the in XAML and assing it a Foreground color from system resource.
For the buttons in the SystemMenuBar there is no issue as they are always on a dark gray background so the black PNG images work just fine.
Hoping this helps.
You can check if the dark theme is in use with this simple check:
public static bool CurrentThemeIsDark
{
get
{
return (Visibility)Application.Current.Resources["PhoneDarkThemeVisibility"] == Visibility.Visible;
}
}
Perhaps hoping in a miracle, but let's try :-)
MyControl derives from Control. Its ControlTemplate contains
<ContentPresenter ContentTemplate="{TemplateBinding EditorTemplate}"/>
(Other details are omitted.)
Derived controls supply suitable EditorTemplate. For example MyTextControl specifies template consisting of a TextBox. (With proper bindings, of course.)
I won't describe what works (most scenarios), but what does not:
A collapsed MyTextControl instance is created. Later on this control is made visible. Here is what happens:
MyTextControl instance created, set to Collapsed
MyTextControl.Loaded event: At this moment the visual tree contains MyTextControl with no children.
In the Loaded handler I call ApplyTemplate(). In turn the visual tree is modified to MyTextControl -> ContentPresenter. That's all, no more children.
Stil in Loaded handler, I assign Loaded handler to the ContentPresenter.
Sometimes later the control is made visible. Its visual tree gets populated by TextBox internals: Border -> ContentControl -> ContentPresenter -> internal TextBoxView. In other words the control just works.
The problem is that the ContentPresenter Loaded handler was not called, i.e. I am not able to identify the moment when the control is ready.
I tried an alternative solution, i.e. instead of forcing ApplyTemplate() I simply waited in MyControl.OnApplyTemplate(). The sequence:
MyTextControl instance created, set to Collapsed
In the Loaded handler the visual tree contains MyTextControl with no children.
The control is made visible.
In OnApplyTemplate() the visual tree is MyTextControl->ContentPresenter.
Stil in OnApplyTemplate(), I assign Loaded handler to the ContentPresenter.
The rest is as before. The visual tree is populated by TextBox internals (the control works), but the above handler gets not called.
Does anybody know a way how to identify the moment when the control is fully loaded?
Note that I did the above with several other MyControl-derived controls. For each of them one of the above scenarios worked (sometimes one, sometimes another), but the TextBox-based control is the first one where I am not able to identify moment of loading.
Also note that this problem does not happen when the control is visible for all the time.
Ok, I'll answer myself. My current conclusion after 1 day and dozens of tests is that Loaded event is for birds. It happens on various stages of the control life cycle and in case of composite controls there is no warranty that the control is fully functional. In some cases it might be not fired at all.
Forcing template building by calling ApplyTemplate() is no solution either as in some cases it may result in building partial control tree.
OnApplyTemplate suffers similar problems - it might be called when only partial control tree is built.
After acknowledging the above statements I decided to give a try to LayoutUpdated event. I set up the handler in OnApplyTemplate() (I tried to use latest possible moment) and investigated the control tree. As a first approximation it seems to be sufficient to check if the ContentPresenter has children. If so, we'll say that the control is loaded and unregister LayoutUpdated handler. A more sofisticated test could be used, but the trivial one I just described is working for wide range of controls.
Originally I was afraid that the LayoutUpdated solution will be inefficient, but it looks like (using the described organization) the first handler call is exactly the place when the control is "loaded".
I'm trying to modify Brian Reindel's Accessible News Slider plugin (sorry, it won't let me link to it and also to my work location), to allow a visitor to fill in multiple copies of a form, sliding back and forth between them. I need for the visitor to be able to add and delete copies of the form from the list. I've modified one of his examples and created a little function to add an element to the list. However, no matter how many times I call the function, it only adds one element, and the plugin is not aware of it; I can see it in the DOM Inspector, but that's it. What am I missing?
this is Brian. Since you're already using jQuery and the plugin, you would gain a great deal by using the library to append elements to the DOM within your custom function. I wanted to give you some guidance, since this is probably more work than you were inititally expecting. Here are some hopefully helpful tips:
The plugin calculates some wrapper
element widths based upon the number
of list items. If you add/remove list
items, then you would need to modify
the calculations that were made or
else it won't scroll properly. You'll probably experience the same types of issues for the click events on the next/previous buttons.
If you have events registered on
elements that you add/remove from the
DOM, then you will need to
re-register those events, since when
the elements are gone, so are the
events that were "bound" to them. It
doesn't look like this is your
problem though at this point.
If you're adding form elements to the
DOM on the fly using the "Add" link,
then the user's cursor focus is no
longer on the form elements, and the
slider is no longer really
accessible. As much as I love
plugging my own plugin, it was meant
mostly to demonstrate usable, custom styled accessible
JavaScript, and I'm not sure it is
flexible enough to do what you want
without some rework.
If you have more specific questions about how to do certain things to get you started on the right track, let me know, and I would be happy to help. Depending on how much you plan to use jQuery on your projects (and I highly recommend that you use it), try out the book Learning jQuery.