wxWidgets wxFrame resize in wxNotebook - visual-c++

I am using wxWidget to design GUI. My GUI has multiple tabs. If user resizes the Frame, if he has selected some tab, when he is switching between tabs same modified size should be maintained. i am using sizers to put all child windows.But currently this is not happening. My current code is like this
void XTab::OnPageChanged(wxNotebookEvent & event)
{
if(isActive())
{
int page = event.GetOldSelection();
if(page!=-1)
{
XPanel * panel = (XPanel*)GetPage(page);
xdmlASSERT(panel->isActive());
panel->onUIDeactivate();
}
page = event.GetSelection();
if(page!=-1)
{
XPanel * panel = (XPanel*)GetPage(page);
xdmlASSERT(!panel->isActive());
panel->onUIActivate();
}
RecalcSize();
DFrame::UpdateLayout(this);
}
}
where DFrame is derived from wxFrame and XPanel is derived from wxPanel.The size is recalculated and best size is queried in GetSizer->CalcMin() method. This happens in ReCalcSize(). I don't know the reason why size of frame set by user is not persisting. Is there any way to store modified size of all children dynamically so? can u send some code for this?

Related

SwiftUI ColorPicker "opened" and "closed" events?

I need to be able to undo / redo the colors that are picked with the new SwiftUI ColorPicker ( on the iPad : it's presented as a floating window )
The thing that makes it very difficult is that there is apparently no way to know that the user has indeed chosen a color ( and therefore closed the panel )
Instead, the behavior of ColorPicker is that it will keep updating the binded color as the user is manipulating the color controls. This is very helpful to show a live preview, but you don't want to register all these color variations for undo / redo purposes : you only want the color that was finally picked.
Therefore there is no logical distinction between the colors that the user tried, and the one that was selected
And I looked everywhere : there aren't any modifiers / notifications related to that.
I know SwiftUI hasn't been there for long, but this seems like a crucial functionality that's missing?
Has anyone found a workaround?
Undo is always tricky. One size does not fit all. In this case a good solution is to throttle the number of events that come into the UndoManager. You can do so by comparing the current time to the time you last commit.
Create a view model that represents your Source of Truth, and conform to ObservableObject to publish events. It will own the UndoManager. It will have a computed property that gets/sets to the internal data, and check the current time against the time of last commit.
class EditViewModel: ObservableObject {
var commitTime = Date.now
let undoManager = UndoManager()
private var _color: Color = .red {
didSet {
objectWillChange.send()
}
}
var color: Color {
get { _color }
set {
let oldValue = color
let now = Date.now
if now.timeIntervalSince(commitTime) > 1 {
undoManager.registerUndo(withTarget: self) {
$0.color = oldValue
}
}
self.commitTime = now
_color = newValue
}
}
}
Now all that's left to do is create your view and pass in the binding. The implementation details are opaque to the View since it is managed by the ViewModel.
struct EditView: View {
#StateObject var vm = EditViewModel()
var body: some View {
Form {
ColorPicker("Color", selection: $vm.color)
}
}
}
If you need even more control, you can additionally compare the last committed color to the new value and only commit if there is a significant change.
I will also agree that a data-driven approach like SwiftUI's can make undo more tricky. For example, when you need to coalesce multiple operations together into one undo group. By its very nature an undo group is procedural-- the user did one thing after the other, and finally terminates on some condition. But I'm sure there is some way to encapsulate this step-wise operation in a transaction object of some kind.
Undo is hard!

Is it possible to recolor a lottie animation programmatically?

If I have a lottie animation in the form of a json file, is there a way to recolor it in code or even within the json itself?
(To be clear, I hope there's a way to do it without involving After Effects. For instance if I decide to change my app's primary color, the whole app will change except the animation unless there's a way to do that.)
I figured it out. For this example, let's say I want to recolor a specific layer to Color.RED.
You'll need your LottieAnimationView, a KeyPath, and a LottieValueCallback
private LottieAnimationView lottieAnimationVIew;
private KeyPath mKeyPath;
private LottieValueCallback<Integer> mCallback;
Then in your onCreate (or onViewCreated for a fragment) you'll get the animation with findViewById, as well as "addLottieOnCompositionLoadedListener" to the lottieAnimationView, in which you will setup the "mKeyPath" and "mCallback":
lottieAnimationVIew = findViewById(R.id.animationView);
lottieAnimationView.addLottieOnCompositionLoadedListener(new LottieOnCompositionLoadedListener() {
#Override
public void onCompositionLoaded(LottieComposition composition) {
mKeyPath = getKeyPath(); // This is your own method for getting the KeyPath you desire. More on that below.
mCallback = new LottieValueCallback<>();
mCallback.setValue(Color.RED);
checkBox.addValueCallback(mKeyPath, LottieProperty.COLOR, mCallback);
}
});
The argument "LottieProperty.COLOR" specifies which property I am changing.
There's probably a better way to do this, but here's my "getKeyPath" method for finding the specific thing I want to change. It will log every KeyPath so you can see which one you want. Then it returns it once you've supplied the correct index. I saw that the one I want is the 5th in the list, hence the hard-coded index of 4.
private KeyPath getKeyPath() {
List<KeyPath> keyPaths = lottieAnimationView.resolveKeyPath(new KeyPath("Fill", "Ellipse 1", "Fill 1"));
for (int i = 0; i < keyPaths.size(); i++) {
Log.i("KeyPath", keyPaths.get(i).toString());
}
if (keyPaths.size() == 5) {
return keyPaths.get(4);
}
else {
return null;
}
}
Note that the "Fill", "Ellipse 1", "Fill 1" are strings I supplied to narrow the list down to just the ones that have those keys, because I know that the layer I want will be among those. There's likely a better way to do this as well.
There is another thread on this topic with the same approach but a bit simplified:
How to add a color overlay to an animation in Lottie?
Here's directly an example (Kotlin):
yourLottieAnimation.addValueCallback(
KeyPath("whatever_keypath", "**"),
LottieProperty.COLOR_FILTER
) {
PorterDuffColorFilter(
Color.CYAN,
PorterDuff.Mode.SRC_ATOP
)
}
You can find the names of the keypaths also in the Lottie editor.

Multithreading in flex web application

I am working on web application. In which i am stuck with some issue.
When i call some server function it will take time to get response. When response have high number of data. It will get data, process on that data and update GUI in background.
Upto that my application GUI freeze. I can not click on any part. I see some where that ActionScript support multithreading. I found some tutorial for that which is here. But, it is for desktop application only.
Is there any way i can handle this freezing of application/GUI in web application. It will decrease my application performance and looks very bad.
Example:
If i have list of data with checkbox and on checkbox click there is some process. Now, there is one button called "Select All". Now, if i click on "select all" then all check box selected and process on check selection is going and freeze the application upto process done.
like: I have following list
<s:List id="tempList" itemRenderer="CustomItemRenderer"
dataProvider="{someList}" useVirtualLayout="false"/>
ItemRenderer have label and checkbox as following.
<s:CheckBox id="cCheckId" selected="{data.selected}"
change="onChangeHandler(event)" />
<s:Label id="lblTest" />
protected function onChangeHandler(event:Event):void
{
data.selected = !data.selected;
}
Now, on button Select all will select all check box.
<s:Button id="btnSelectAll" label="Select All" click="selectAllHandler(event)" />
protected function selectAllHandler(event:MouseEvent):void
{
for(var i:int = 0;i<someList.length;i++)
{
someList[i].selected = true;
}
}
Now, if someList have lots of data then it will freeze the screen.
Any help is greatly appreciated.
The main idea behind the list and itemrenderers that you have a list (or datagrid) that displays like 30 items and then you can scroll to see the rest. Then you will only have 30 Itemrenderers that would be updated at once.
If you don't want to scroll you will need to distribute your item selection over several frames, something like that (untested, but you get the idea)
private static const ITEMS_AT_ONCE:int = 5000;
private var _currentIndex:int;
protected function selectAllHandler(event:MouseEvent):void
{
_currentIndex = 0;
addEventListener(Event.ENTER_FRAME, onEnterFrame); // this will call the onEnterFrame method on each frame rendered
}
private function onEnterFrame(e:Event):void
{
// make sure we don't run out of bounds of the dataprovider's length
var maxIndex:int = Math.min(_currentIndex + ITEMS_AT_ONCE, someList.length);
// set selection for the current bunch
for (var i:int = _currentIndex; i < maxIndex; i++)
{
someList[i].selected = true;
}
if (maxIndex == someList.length)
{
// We are done, remove enterframe listener
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
// I'm not sure but don't you need to refresh the dataprovider to reflect the changes in the ItemRenderers ?
// (someList.dataProvider as ArrayCollection).refresh();
}
else
{
// update the _currentindex so we continue after this item on the next frame
_currentIndex = maxIndex;
}
Another possible solution - if you display all of them anyways - you might try to switch to a VGroup that will hold custom UIComponents (without MXML) for the items - this should speed up the rendering.

xna how to setup controls in game

I want to be able to go to options menu in the game I am developing and set up my controls.
It is a simple game of pong (for now) and the controls for each player are just up and down.
This is how I want the process to look like: I click SETUP CONTROLS, game displays the name of the control I am supposed to change and it waits, I click the button on keyboard that i want it to be changed to, game reads it and displays the next control I am supposed to change and so on until i change all controls.
I have found a way how to do that here and my code now looks basicly like this:
if (optionsBList.IsButtonClicked("SETUP CONTROLS")) //when i click the
//SETUP CONTROLS button
//in the options menu
{
KeyboardState currentKeyboardState = new KeyboardState();
waitingForKey = true;
while (waitingForKey)
{
if(currentKeyboardState.GetPressedKeys().Count() > 0)
{
player1.upkey = currentKeyboardState.GetPressedKeys()[0];
//the path for the key isn't player1.upkey, but lets say it is.
waitingForKey = false;
}
}
}
In this short code my goal is to change just one key. If I can make it change 1 key, changing more wont be a problem.
The problem is, I don't see why does my game stop responding when i click the SETUP CONTROLS button. I don't see an infinite loop here nor a memory leak.
Why is my game crashing and is there a better way to load controls in options menu?
If you saw the answer from the link you placed in your question, you would have noticed that he actually deleted the while loop and he made it an if statement.
Like Nico Schertler said : "while(waitingForKey) is your infinite loop. That loop blocks the game thread, so no further input is recognized."
Link to the answer from your link: https://stackoverflow.com/a/15935732/3239917
if (optionsBList.IsButtonClicked("SETUP CONTROLS")) //when i click the
//SETUP CONTROLS button
//in the options menu
{
KeyboardState currentKeyboardState = new KeyboardState();
waitingForKey = true;
if (waitingForKey )
{
if(currentKeyboardState.GetPressedKeys().Count() > 0)
{
player1.upkey = currentKeyboardState.GetPressedKeys()[0];
//the path for the key isn't player1.upkey, but lets say it is.
waitingForKey = false;
}
}
}

Shrink window in GTK+ dynamically when content shrinks?

I have a window in a Vala application and an image inside it.
This image is changed sometimes by img.set_from_pixbuf(imgdata); and so it's size changes as well. It's embedded in a Gtk.Box.
box = new Gtk.Box(Orientation.VERTICAL,5);
...
box.pack_end(img,false,false);
So if there was a big image before and I replace it with a smaller one, the window remains ridiculously big and I have not found a method to dynamically shrink it to the space required.
I have tried with window.set_default_size(box.width_request,box.height_request) but it always returns -1.
So any ideas how to resize the window?
Thanks!
I have fought with this issue myself and while the accepted answer is correct, I though I could give a more "complete" answer, with working code.
Reproducing the problem
The following code (In C++, sorry) reproduces your issue:
#include <array>
#include <gtkmm.h>
class ResizableWindow : public Gtk::Window
{
public:
ResizableWindow()
: m_toggle{"Toggle"}
, m_currentImageIndex{0}
{
m_files[0] = "small.png";
m_files[1] = "large.png";
// Setup window layout:
m_layout.attach(*Gtk::manage(new Gtk::Image(m_files[m_currentImageIndex])), 0, 0, 1, 1);
m_layout.attach(m_toggle, 0, 1, 1, 1);
add(m_layout);
// Set up signal handlers:
m_toggle.signal_clicked().connect([this](){OnToggle();});
}
private:
void OnToggle()
{
// Switch image file:
if(m_currentImageIndex == 0)
{
m_currentImageIndex = 1;
}
else
{
m_currentImageIndex = 0;
}
// Load new image.
Gtk::Widget* child = m_layout.get_child_at(0, 0);
Gtk::Image* currentImage = dynamic_cast<Gtk::Image*>(child);
currentImage->set(m_files[m_currentImageIndex]);
}
Gtk::Grid m_layout;
Gtk::Button m_toggle;
std::array<std::string, 2> m_files;
size_t m_currentImageIndex;
};
int main (int argc, char* argv[])
{
auto app = Gtk::Application::create(argc, argv, "so.question.q8903140");
ResizableWindow w;
w.show_all();
return app->run(w);
}
The Toggle button changes the underlying images. Both are the same image, but with different sizes. Notice that, As you already mentionned, when toggling for the first time (small --> large), the window resizes appropriately. However, when toggling a second time (large --> small), the image is resized, but not the window, leaving extra space around the image:
Weird, I know...
Solution
To solve the issue, one needs to call the resize method. So the Toggle handler would become:
void OnToggle()
{
if(m_currentImageIndex == 0)
{
m_currentImageIndex = 1;
}
else
{
m_currentImageIndex = 0;
}
Gtk::Widget* child = m_layout.get_child_at(0, 0);
Gtk::Image* currentImage = dynamic_cast<Gtk::Image*>(child);
currentImage->set(m_files[m_currentImageIndex]);
// Resize window:
resize(1, 1);
}
Note that resize was called with dimensions 1x1 (smallest possible dimensions). Gtkmm will resize the window following geometry constraints automatically from there.
If I am not mistaken the automatic resizing of windows only only happens when elements are too large to be drawn. Additionally the set_default_size method only matters when first drawing the window and unless I am wrong is never used again. I would suggest using the resize method to set the window size. (link)
window.resize(box.width_request, box.height_request);
One thing you need to remember when using resize if you can't resize it smaller than the request_size if you run into that issue use the set_request_size method.

Resources