I have a toolbar controller which is capable of updating the toolbar state ( enabled/disabled, pressed/unpressed ) by querying document properties or the application framework. I have some buttons that represent the current state of a view.
From an application design standpoint I like having toolbar controller able to update the button state at any time given a document. I also prefer the toolbar controller & button handlers to have no internal state.
Options as I see it - looking for other suggestions:
Create a mechanism for visiting all views of a document with a visitor that can capture the state of the view which is then used to enable/disable/press/depress the button.
Create some connection between views and toolbar handlers that allows the toolbar buttons to directly ask the views.
Other??
you can try having an event loop for the view and update the state with a function call dispatch
Like this:
class ViewEventArgs{
public:
int eventNumber;
};
class ViewEvent{
public:
virtual void onViewChange(ViewEventChangeArgs args) = 0;
};
class ViewController{
public:
virtual void doPressed() = 0;
virtual void doChecked() = 0;
//other interface methods
};
class ToolbarView : public ViewEvent{
public:
//Your EVENT-LOOP kernel will fire these events depending upon the state change in the view
void onViewChange(ViewEventChangeArgs args)
{
switch(args.eventNumber){
case PRESSED:
getToolbarController()->doPressed();//the method dispatch
break;
case CHECKED:
getToolbarController()->doChecked();
}
}
//other parts of the view
};
class ToolbarController: public ViewController{
public:
void doPressed() { /*pressed*/ }
void doChecked() { /*checked*/ }
//implementations
};
Related
I create a new class extend CEdit to override some of the message handles.
My ultimate goal is when edit control is on focus, some of the toolbar buttons become available.
I created a bool variable in doc. then the pCmdUI->enable() set to this bool. The onfocus is overridden in new edit control class. I'm having trouble to update this bool vairbale from the onfocus message handle.
void CMFCDoc::OnUpdateTextColor(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(shape_onfocus_);
}
class CMFCDoc : public COleServerDoc
{
...
bool shape_onfocus_;
}
//edit control
#include <afxwin.h>
class CEditControl :
public CEdit
{
public:
CEditControl();
~CEditControl();
DECLARE_MESSAGE_MAP()
afx_msg void OnEnSetfocus();
};
void CEditControl::OnEnSetfocus()
{
//----- I want to update shape_onfocus_ here. -----
this->SetWindowTextA(_T("Hello world"));
}
Assuming your CEditControl instance is a child of some sort of CView, you could go about it like this:
void CEditControl::OnEnSetfocus()
{
CView *view = static_cast<CView *>(GetParent());
CMFCDoc *doc = static_cast<CMFCDoc *>(view->GetDocument());
doc->shape_onfocus_ = true;
...
}
Assuming the edit-control is a child of a CView-derived class, you should better put the OnUpdateUI() handler in the view class, not the document one.
For example, if the view-class is CFormView-derived (dialog), you could simply write:
void CMyView::OnUpdateTextColor(CCmdUI *pCmdUI)
{
pCmdUI->Enable(GetFocus()==GetDlgItem(IDC_MYEDIT));
}
This piece of code works for both SDI and MDI applications.
If the view class is not CFormView-derived (the edit-box was created programmatically), the code above could be modified slightly, and instead of calling GetDlgItem() you should enumerate the view's children list (search your edit-box there).
If the only reason to override the edit-control was to capture the EN_SET/KILLFOCUS messages, sorry this wasn't worth the effort, as you could simply capture these in the view's code. Then the view's message-map would contain:
ON_EN_SETFOCUS(IDC_MYEDIT, &CMyView::OnEnSetfocusMyEdit)
ON_EN_KILLFOCUS(IDC_MYEDIT, &CMyView::OnEnKillfocusMyEdit)
and the view-class code:
void CMyView::OnEnSetfocusMyEdit()
{
// TODO: Add your control notification handler code here
}
void CMyView::OnEnKillfocusMyEdit()
{
// TODO: Add your control notification handler code here
}
These are generated by the wizard. Go to the Class View tab, select your class and then go to the Events page; in the Controls subtree you can find your control and add handlers for its events. But all this is not needed, as you can just use GetFocus()/GetDlgItem() as suggested above.
And as other members said, you can access the document class from any of its views by calling the GetDocument() function.
I'm struggling to figure out how to properly override a button's ButtonStateChange in the JUCE library. I'm wanting to change the what happens when a button is held down. I'm fairly new to overriding, but I've been able to successfully override other elements in the JUCE library. Though I am having an issue with this topic.
1) I know you create a new class, maybe MyCustomButton, then
2) Inherit the class you are looking to modify, Button::Listener (not sure if I should do private or public inheritance)
3) Copy and paste the code of the function you want to alter, applying the override keyword to the prototype,
but after this, I'm lost. I'm not sure how to let this new class affect a button that already exists. I know i need to add a listener to an existing button in the constructor and remove the listener in the destructor of the GUI component, but still, I don't know how to apply this new ButtonChangeState listener to an existing button.
Any help would be greatly appreciated.
You can create a new class which inherits from one of Juce's button classes (e.g juce::TextButton) and override buttonStateChanged()
class MyCustomButton : public juce::TextButton
{
public:
MyCustomButton();
protected:
void buttonStateChanged() override
{
// do what you want here
}
};
To apply to your already existing button, just change its type to MyCustomButton.
Alternatively, you can make the class where you use the button inherit from juce::Button::Listener and override buttonStateChanged(Button*).
Then all you need is to attach the listener to your button:
class MyWindow : public Component, private juce::Button::Listener
{
public:
MyWindow()
{
m_button.addListener(this);
}
~MyWindow()
{
m_button.removeListener(this);
}
private:
juce::TextButton m_button;
void buttonStateChanged(Button* button) override
{
if (button == &m_button)
{
// do what you want
}
}
};
I have few questions on this Subjects.
I created a class for buttons, the class has problem.
Problem is:
1. I wanna create function to be called if button is clicked, the problem is that every single button gonna do different thing if it was clicked. So i don't know how i can create function that will do different thing for every button.
I have no idea how i should design my interface.
If you can give me an idea on how i should design my GUI that would be great.
This is my button class
class GUIButtons
{
public:
GUIButtons(void);
~GUIButtons(void);
void LoadMesh(string fileName, int startAnimation, LPDIRECT3DDEVICE9 d3ddev);
void Render(float timeElapsed, D3DXMATRIX *matWorld);
void EventProc(HWND hWnd, UINT msg, LPDIRECT3DDEVICE9 d3ddev);
void Picking(HWND hWnd, LPDIRECT3DDEVICE9 d3ddev);
private:
CXFileEntity *Button;
};
EDIT 2:
Guys is this possible?
I create two functions and than ill point one function to another.
Something like this
void a()
{
....
}
void b() = a;
EDIT 3:
Ok should i use this way for the onClick() function.
void Onclick( void(*fun) )
{
fun();
}
i pass a function to OnClick than it calls the function.
should i use this way?
Use inheritance/polymorphism: The base class is GUIButtons, and every new individual button derives from that base clase:
class MyButton : public GUIButtons { ... }
And then the functionality for a click comes in a virtual method onClick() or whatever.
More detail:
class GUIButtons
{
... \\ lots of stuff
virtual void onClick() { };
};
class CloseButton : public GUIButtons
{
...
virtual void onClick()
{
//code to close window
}
};
class SettingsButton : public GUIButtons
{
...
virtual void onClick()
{
//stuff to open settings menu
}
};
Button click is an action/event. You can encapsulate the click action as a class. This action is interpreted and used differently by the application that uses the button widget. The gui library has to notify that a button has been clicked with the relevant information. You can refer to popular GUI libraries like Qt or Gtk+ as examples to know how they implement GUI events and much more.
I recommend you the book "DirectX 9 User Interfaces: Design and Implementation". I have it and i may say that you'll find there everything what you need!!!;)
I am refactoring some code to decouple GUI from some state.
#include <StateObject>
Class GUI{
...
StateObject A;
void doSomething() { A->hullaballoo();}
**void ReFreshMyGui() { //take state A and redraw }**
};
State object is being shared by multiple classes to update the state but this Gui Object specializes in displaying the state. So I would like to call the Refresh function via StateObject whenever its modified.
I am not sure how or if signals will provide the solution. Any hints?
In order to decouple GUI and Data you could use the MVC pattern. This means your GUI should register to your model's (data) object(s) and whenever the data changes the GUI will be notified and it will be the GUI to redraw itself.
But careful, the model should not have the notion of a concrete GUI, instead the GUI should implement an observer interface containing a method (e.g. void Update()) that will be called whenever changes occur (notification handler).
Just look for the MVC-pattern on google. You'll find thousands of useful tutorials.
You may also take in consideration the MVP and the MVVM patterns.
Example:
class Observer
{
virtual void Update(void* data) = 0;
}
class GUI : public Observer
{
public:
virtual void Update(void* data)
{
//Redraw method and some other things you may
//want to do with the new data
}
}
class Model
{
private:
int m_iData;
List<Observer> observers;
public:
void SetData(int iData)
{
m_iData = iData;
for(int i = 0; i < observers.Length; i++)
{
observers[i].Update(NULL);
}
}
}
I'm building an application using the Supervising Controller pattern (Model View Presenter) and I am facing a difficulty. In my page I have a repeater control that will display each item of a collection I am passing to it. The reapeater item contains 2 dropdown list that allow the user to select a particular value. When I click the next button, I want the controller to retrieve those values.
How can I do that I a clean way?
You can also make a 'widget' interface for the drop down. I'll give you an easy example of a some working code for a TextBox widget so you get the idea.
public interface ITextWidget
{
event EventHandler TextChanged;
string Text { get; set; }
}
public abstract class TextWidget<T> : ITextWidget
{
protected T _wrappedWidget { get; set; }
public event EventHandler TextChanged;
protected void InvokeTextChanged(object sender, EventArgs e)
{
var textChanged = TextChanged;
if (textChanged != null) textChanged(this, e);
}
public abstract string Text { get; set; }
}
Notice that so far everything is technology agnostic. Now here's an implementation for a Win Forms TextBox:
public class TextBoxWidget : TextWidget<TextBox>
{
public TextBoxWidget(TextBox textBox)
{
textBox.TextChanged += InvokeTextChanged;
_wrappedWidget = textBox;
}
public override string Text
{
get { return _wrappedWidget.Text; }
set { _wrappedWidget.Text = value; }
}
}
This gets instantiated in the Form itself, which back to MVP is also the IViewWhatever:
public partial class ProjectPickerForm : Form, IProjectPickerView
{
private IProjectPickerPresenter _presenter;
public void InitializePresenter(IProjectPickerPresenter presenter) {
_presenter = presenter;
_presenter.InitializeWidgets(
...
new TextBoxWidget(txtDescription));
}
...
}
And in the Presenter:
public class ProjectPickerPresenter : IProjectPickerPresenter
{
...
public void InitializeWidgets(ITextWidget descriptionFilter) {
Check.RequireNotNull<ITextWidget>(descriptionFilter, "descriptionFilter");
DescriptionFilter = descriptionFilter;
DescriptionFilter.Text = string.Empty;
DescriptionFilter.TextChanged += OnDescriptionTextChanged;
}
...
public void OnDescriptionTextChanged(object sender, EventArgs e) {
FilterService.DescriptionFilterValue = DescriptionFilter.Text;
}
It's looks worse than it is to setup because most of the work is fairly mechanical once you get the idea. The clean part is that the presenter can get (and set) whatever info it needs on the widget without knowing or caring what the actual implemented widget is. It also lends itself to reuse with other widgets (you wind up building a library of them) of the same type (Win Forms here) and in other UI technologies as needed (once you have the interface / base class the implementation in another technology is trivial). It also is easy to test with mock objects because you have the interface. And your UI is now wonderfully ignorant of just about everything but UI related tasks. The downside is the bunch of classes per widget and a little learning curve to get comfortable with it.
For your drop down, your might just need the SelectedIndexChanged type event, which you'd substitute for this examples TextChanged event.
When controller-view interation get's too complex I usually split them up into subcontrollers and subviews.
You can have the items in the repeater be user-controls that have their own views and controllers. Your main view can then have a list of subviews(usercontrols) that have their own controllers that are maintained by the main controller.
When the user clicks next your main controller can signal all the subcontrollers to refresh their items from their views.