I am trying to implement a menu bar with a more familiar behavior. I understand I can do this with item lists and javascript, but I wish to do it within Wt as an exercise.
I have attached the program and makefile. My menu bar consists of 2 text labels on the left side of the window. When a mouse button is pressed on one of the labels, a popup menu will be shown. After a mousebutton is pressed, then on mouse over to either label, the popup menu for that label will be shown and any other already shown popup menu will be hidden. I am using printf debugging and wireshark to try to understand what is happening. case 1: After clicking on the label "menu1", it's popup menu correctly appears. Keeping the mouse button depressed, if I move my mouse up out of the browsers content area and loop around to label "menu2", then it's popup menu correctly appears. So far, so good. case 2: Here's the part that I don't understand, if I restart the session and click on label "menu1", it's popup menu appears. Keeping the mouse button depressed, if I move the mouse cursor up off the label, then loop around, then quckly pass across label "menu2" then "menu1", both popup menus appear at the same time. It is this change in behavior depending on how fast I move the mouse cursor across the labels that concerns me. According to my printf debugging and wireshark, the mouse events are all being received, and are received in the correct order. According to wireshark, in case 1, 1 or 2 mouse events are sent in each POST. In case 2, there are 4 mouse events that are sent in 1 POST. I am including the javascript I retrieved over wireshark for perusal. I think I understand most of the javascript that is being sent from the server to the client. However, in case 2, the javascript seems incorrect. Please advise. -Dave
label "menu1" id=oaokmkp
popup id=oaokmkr
item1 id=oaokmkx
item2 id=oaokml0
label "menu2" id=oaokml2
popup id=oalkml4
item3 id=oaokmla
item4 id=oaokmld
// case 2: moving over the MenuBarItems quickly
request=jsupdate
&signal=sd&focus=&tid=oaokml2&type=mouseover&clientX=42&clientY=65&documentX=42&documentY=65&dragdX=-14&dragdY=35&wheel=0&screenX=42&screenY=205&scrollX=0&scrollY=0&width=0&height=0&widgetX=24&widgetY=17&button=1
&e1signal=se&e1focus=&e1tid=oaokml2&e1type=mouseout&e1clientX=44&e1clientY=39&e1documentX=44&e1documentY=39&e1dragdX=-12&e1dragdY=9&e1wheel=0&e1screenX=44&e1screenY=179&e1scrollX=0&e1scrollY=0&e1width=0&e1height=0&e1widgetX=26&e1widgetY=-9&e1button=1
&e2signal=s5&e2focus=&e2tid=oaokmkp&e2type=mouseover&e2clientX=44&e2clientY=39&e2documentX=44&e2documentY=39&e2dragdX=-12&e2dragdY=9&e2wheel=0&e2screenX=44&e2screenY=179&e2scrollX=0&e2scrollY=0&e2width=0&e2height=0&e2widgetX=26&e2widgetY=21&e2button=1
&e3signal=s6&e3focus=&e3tid=oaokmkp&e3type=mouseout&e3clientX=49&e3clientY=5&e3documentX=49&e3documentY=5&e3dragdX=-7&e3dragdY=-25&e3wheel=0&e3screenX=49&e3screenY=145&e3scrollX=0&e3scrollY=0&e3width=0&e3height=0&e3widgetX=31&e3widgetY=-13&e3button=1&ackId=4&pageId=0
{
function f26(event){
var g = event||window.event; var t = g.target||g.srcElement;
if ((!t||Wt3_1_8.hasTag(t,'DIV') ||Wt3_1_8.hasTag(t,'BODY')
||Wt3_1_8.hasTag(t,'HTML'))) {
var e=event||window.event,o=this;
if((e.keyCode && e.keyCode == 27)){
Wt._p_.update(this,'s13',e,true);
}
}
}
document.onkeydown=f26;
function f27(event){
var e=event||window.event,o=this;
Wt._p_.update(o,'s14',e,true);
}
var j28=$('#oaokmkh').get(0);
j28.onclick=f27;
Wt3_1_8.show('oaokmkr'); // show
popupmenu1 - this seems wrong: should have show 2, hide 1, show 1, hide 2
Wt3_1_8.hide('oaokml4'); // hide
popupmenu2
var j29=$('#oaokmkp').get(0);
j29.style.color='rgb(255,255,255)';
j29.style.backgroundColor='#6880A0';
var j30=$('#oaokml2').get(0);
j30.style.color='rgb(0,0,0)';
j30.style.backgroundColor='rgb(255,255,255)';
var j31=$('#oaokmkx').get(0); // hide
menuitem1 - this seems wrong: not all menu items should be hidden
$('#oaokmkx').addClass('Wt-item');
$('#oaokmkx').addClass('Wt-item');
$('#oaokmkx').addClass('Wt-item');
$('#oaokmkx').removeClass('Wt-selected');
$('#oaokmkx').removeClass('Wt-selected');
$('#oaokmkx').removeClass('Wt-selected');
var j32=$('#oaokml0').get(0); // hide
menuitem2
$('#oaokml0').addClass('Wt-item');
$('#oaokml0').addClass('Wt-item');
$('#oaokml0').addClass('Wt-item');
$('#oaokml0').removeClass('Wt-selected');
$('#oaokml0').removeClass('Wt-selected');
$('#oaokml0').removeClass('Wt-selected');
var j33=$('#oaokmla').get(0); // hide
menuitem3
$('#oaokmla').addClass('Wt-item');
$('#oaokmla').addClass('Wt-item');
$('#oaokmla').addClass('Wt-item');
$('#oaokmla').removeClass('Wt-selected');
$('#oaokmla').removeClass('Wt-selected');
$('#oaokmla').removeClass('Wt-selected');
var j34=$('#oaokmld').get(0); // hide
menuitem4
$('#oaokmld').addClass('Wt-item');
$('#oaokmld').addClass('Wt-item');
$('#oaokmld').addClass('Wt-item');
$('#oaokmld').removeClass('Wt-selected');
$('#oaokmld').removeClass('Wt-selected');
$('#oaokmld').removeClass('Wt-selected');
Wt3_1_8.positionAtWidget('oaokml4','oaokml2',Wt3_1_8.Horizontal);
// position menus near labels
Wt3_1_8.positionAtWidget('oaokmkr','oaokmkp',Wt3_1_8.Horizontal);
Wt.layouts.adjust('oaokmlg');
Wt.layouts.adjust('oaokmkm');
}
Wt._p_.response(5);
// case 1: Moving over MenuBarItems slowly
request=jsupdate&signal=sd&focus=&tid=oaokml2&type=mouseover&clientX=37&clientY=71&documentX=37&documentY=71&dragdX=-19&dragdY=41&wheel=0&screenX=37&screenY=211&scrollX=0&scrollY=0&width=0&height=0&widgetX=19&widgetY=23&button=1&ackId=5&pageId=0
{
function f35(event){
var g = event||window.event; var t = g.target||g.srcElement;
if ((!t||Wt3_1_8.hasTag(t,'DIV') ||Wt3_1_8.hasTag(t,'BODY')
||Wt3_1_8.hasTag(t,'HTML'))){
var e=event||window.event,o=this;
if((e.keyCode && e.keyCode == 27)){
Wt._p_.update(this,'s13',e,true);
}
}
}
document.onkeydown=f35;
function f36(event){
var e=event||window.event,o=this;
Wt._p_.update(o,'s14',e,true);
}
var j37=$('#oaokmkh').get(0);
j37.onclick=f36;
Wt3_1_8.hide('oaokmkr'); // hide
popupmenu1
Wt3_1_8.show('oaokml4'); // show
popupmenu2
var j38=$('#oaokmkp').get(0);
j38.style.color='rgb(0,0,0)';
j38.style.backgroundColor='rgb(255,255,255)';
var j39=$('#oaokml2').get(0);
j39.style.color='rgb(255,255,255)';
j39.style.backgroundColor='#6880A0';
var j40=$('#oaokmkx').get(0);
$('#oaokmkx').addClass('Wt-item');
$('#oaokmkx').addClass('Wt-item');
$('#oaokmkx').removeClass('Wt-selected');
$('#oaokmkx').removeClass('Wt-selected');
var j41=$('#oaokml0').get(0);
$('#oaokml0').addClass('Wt-item');
$('#oaokml0').addClass('Wt-item');
$('#oaokml0').removeClass('Wt-selected');
$('#oaokml0').removeClass('Wt-selected');
var j42=$('#oaokmla').get(0);
$('#oaokmla').addClass('Wt-item');
$('#oaokmla').removeClass('Wt-selected');
var j43=$('#oaokmld').get(0);
$('#oaokmld').addClass('Wt-item');
$('#oaokmld').removeClass('Wt-selected');
Wt3_1_8.positionAtWidget('oaokml4','oaokml2',Wt3_1_8.Horizontal);
Wt.layouts.adjust('oaokmlg');
Wt.layouts.adjust('oaokmkm');
}
Wt._p_.response(6);
request=jsupdate
&signal=se&focus=&tid=oaokml2&type=mouseout&clientX=41&clientY=47&documentX=41&documentY=47&dragdX=-15&dragdY=17&wheel=0&screenX=41&screenY=187&scrollX=0&scrollY=0&width=0&height=0&widgetX=23&widgetY=-1&button=1
&e1signal=s5&e1focus=&e1tid=oaokmkp&e1type=mouseover&e1clientX=41&e1clientY=41&e1documentX=41&e1documentY=41&e1dragdX=-15&e1dragdY=11&e1wheel=0&e1screenX=41&e1screenY=181&e1scrollX=0&e1scrollY=0&e1width=0&e1height=0&e1widgetX=23&e1widgetY=23&e1button=1&ackId=6&pageId=0
{
function f44(event){
var g = event||window.event;
var t = g.target||g.srcElement;
if ((!t||Wt3_1_8.hasTag(t,'DIV') ||Wt3_1_8.hasTag(t,'BODY')
||Wt3_1_8.hasTag(t,'HTML'))){
var e=event||window.event,o=this;
if((e.keyCode && e.keyCode == 27)){
Wt._p_.update(this,'s13',e,true);
}
}
}
document.onkeydown=f44;
function f45(event){
var e=event||window.event,o=this;
Wt._p_.update(o,'s14',e,true);
}
var j46=$('#oaokmkh').get(0);
j46.onclick=f45;
Wt3_1_8.show('oaokmkr');
// show popupmenu1
Wt3_1_8.hide('oaokml4');
// hide popupmenu2
var j47=$('#oaokmkp').get(0);
// change appearance of menu1 label
j47.style.color='rgb(255,255,255)';
j47.style.backgroundColor='#6880A0';
var j48=$('#oaokml2').get(0);
// change appearance of menu2 label
j48.style.color='rgb(0,0,0)';
j48.style.backgroundColor='rgb(255,255,255)';
var j49=$('#oaokmkx').get(0);
// show menuitem1
$('#oaokmkx').addClass('Wt-item');
$('#oaokmkx').removeClass('Wt-selected');
var j50=$('#oaokml0').get(0);
// show menuitem2
$('#oaokml0').addClass('Wt-item');
$('#oaokml0').removeClass('Wt-selected');
var j51=$('#oaokmla').get(0);
// hide menuitem3
$('#oaokmla').addClass('Wt-item');
$('#oaokmla').addClass('Wt-item');
$('#oaokmla').removeClass('Wt-selected');
$('#oaokmla').removeClass('Wt-selected');
var j52=$('#oaokmld').get(0);
// hide menuitem4
$('#oaokmld').addClass('Wt-item');
$('#oaokmld').addClass('Wt-item');
$('#oaokmld').removeClass('Wt-selected');
$('#oaokmld').removeClass('Wt-selected');
Wt3_1_8.positionAtWidget('oaokmkr','oaokmkp',Wt3_1_8.Horizontal);
// position menu1 at menubar
Wt.layouts.adjust('oaokmlg');
Wt.layouts.adjust('oaokmkm');
}
Wt._p_.response(7);
request=jsupdate&signal=s6&focus=&tid=oaokmkp&type=mouseout&clientX=53&clientY=17&documentX=53&documentY=17&dragdX=-3&dragdY=-13&wheel=0&screenX=53&screenY=157&scrollX=0&scrollY=0&width=0&height=0&widgetX=35&widgetY=-1&button=1&ackId=7&pageId=0
{}
Wt._p_.response(8);
/* Copyright 2010 by David A. Betz. This file is part of WebSchedule. WebSchedule is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. WebSchedule is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with WebSchedule. If not, see <http://www.gnu.org/licenses/>. */ #include <iostream> #include <Wt/WApplication> #include <Wt/WCompositeWidget> #include <Wt/WContainerWidget> #include <Wt/WEnvironment> #include <Wt/WHBoxLayout> #include <Wt/WPopupMenu> #include <Wt/WText> #include <Wt/WVBoxLayout> using namespace Wt; typedef WPopupMenu WMenuBarPopup; class WT_API WMenuBarItem { public: WInteractWidget *label_; WMenuBarPopup *popup_; WMenuBarItem(WInteractWidget *label, WMenuBarPopup *popup) : label_(label), popup_(popup) { std::cerr << "id=" << label_->id() << std::endl; } WInteractWidget *Label(){ return label_; } WMenuBarPopup *Popup(){ return popup_; } void renderSelected(bool selected, Orientation orientation){ if (selected){ WCssDecorationStyle& decoration=Label()->decorationStyle(); decoration.setBackgroundColor(WColor("#6880A0")); decoration.setForegroundColor(white); std::cerr << "selecting popup " << popup_->id() << std::endl; popup_->popup(label_,orientation); } else { WCssDecorationStyle& decoration=Label()->decorationStyle(); decoration.setBackgroundColor(white); decoration.setForegroundColor(black); std::cerr << "hiding popup " << popup_->id() << std::endl; popup_->hide(); } } }; class WT_API WMenuBar : public WCompositeWidget { public: WMenuBar(Orientation orientation); WMenuBarPopup *addItem(const WString& text); WPopupMenuItem *result() const { return result_; } WMenuBarItem *findItemFromLabel(WInteractWidget *label){ for(size_t i=0; i<menuBarItems_.size(); ++i) if (menuBarItems_[i]->Label()==label) return menuBarItems_[i]; throw "WMenuBar::findItemFromLabel: cannot find item"; } protected: void renderUnselectedAll(void); void mouseDown(WInteractWidget *text, const WMouseEvent& e); void mouseUp(WInteractWidget *text, const WMouseEvent& e); void mouseOver(WInteractWidget *text, const WMouseEvent& e); void mouseOut(WInteractWidget *text, const WMouseEvent& e); void done(WPopupMenuItem *result); boost::signals::connection globalMouseWentDownConnection_, globalMouseWentUpConnection_, globalEscapeConnection_; bool recursiveEventLoop_; WContainerWidget *container_; WBoxLayout *menuBarLayout_; Orientation orientation_; WPopupMenuItem *result_; std::vector<WMenuBarItem *> menuBarItems_; WMenuBarItem *activeMenuBarItem_; Signal<> aboutToHide_; }; WMenuBar::WMenuBar(Orientation orientation) : WCompositeWidget(), recursiveEventLoop_(false), result_(0), orientation_(orientation), activeMenuBarItem_(0) { setImplementation(container_=new WContainerWidget); if (orientation_==Vertical) container_->setLayout(menuBarLayout_=new WVBoxLayout); else container_->setLayout(menuBarLayout_=new WHBoxLayout); menuBarLayout_->addStretch(100); } WMenuBarPopup *WMenuBar::addItem(const WString& text) { WText *label=new WText(text); WMenuBarItem *item=new WMenuBarItem(label, new WMenuBarPopup); menuBarLayout_->removeItem(menuBarLayout_->itemAt(menuBarLayout_->count()-1)); menuBarLayout_->addWidget(label,0,AlignTop); menuBarLayout_->addStretch(100); menuBarItems_.push_back(item); label->mouseWentDown().connect(boost::bind(&WMenuBar::mouseDown,this,item->Label(),_1)); label->mouseWentUp().connect(boost::bind(&WMenuBar::mouseUp,this,item->Label(),_1)); label->mouseWentOver().connect(boost::bind(&WMenuBar::mouseOver,this,item->Label(),_1)); label->mouseWentOut().connect(boost::bind(&WMenuBar::mouseOut,this,item->Label(),_1)); return item->Popup(); } void WMenuBar::renderUnselectedAll(void){ for(size_t i=0; i<menuBarItems_.size(); ++i) menuBarItems_[i]->renderSelected(false,orientation_==Vertical?Horizontal:Vertical); } void WMenuBar::mouseDown(WInteractWidget *label, const WMouseEvent& e){ WMenuBarItem *item=findItemFromLabel(label); std::cerr << "entering mouseDown " << item->Label()->id() << std::endl; renderUnselectedAll(); std::cerr << "\tshowing " << item->Label()->id() << std::endl; item->renderSelected(true,orientation_==Vertical?Horizontal:Vertical); recursiveEventLoop_=true; activeMenuBarItem_=item; } void WMenuBar::mouseUp(WInteractWidget *label, const WMouseEvent& e){ WMenuBarItem *item=findItemFromLabel(label); std::cerr << "mouseUp " << item->Label()->id() << std::endl; } void WMenuBar::mouseOver(WInteractWidget *label, const WMouseEvent& e){ WMenuBarItem *item=findItemFromLabel(label); std::cerr << "entering mouseOver " << item->Label()->id() << std::endl; if (recursiveEventLoop_ && item!=activeMenuBarItem_){ std::cerr << "\thiding " << activeMenuBarItem_->Label()->id() << std::endl; activeMenuBarItem_->renderSelected(false,orientation_==Vertical?Horizontal:Vertical); std::cerr << "\tshowing " << item->Label()->id() << std::endl; item->renderSelected(true,orientation_==Vertical?Horizontal:Vertical); activeMenuBarItem_=item; } std::cerr << "leaving mouseOver " << item->Label()->id() << std::endl; } void WMenuBar::mouseOut(WInteractWidget *label, const WMouseEvent& e){ WMenuBarItem *item=findItemFromLabel(label); std::cerr << "mouseOut " << item->Label()->id() << std::endl; } void WMenuBar::done(WPopupMenuItem *result) { result_ = result; WApplication::instance()->root()->clicked() .disconnect(globalMouseWentDownConnection_); WApplication::instance()->root()->mouseWentUp() .disconnect(globalMouseWentUpConnection_); WApplication::instance()->globalEscapePressed() .disconnect(globalEscapeConnection_); recursiveEventLoop_ = false; aboutToHide_.emit(); } class ScheduleApplication : public WApplication { private: WHBoxLayout *hbox_; WVBoxLayout *lhs_vbox_; public: ScheduleApplication(const Wt::WEnvironment& env) : WApplication(env){ useStyleSheet("https://www.memorial-anesthesia.org/everywidget.css"); WMenuBar *mb=new WMenuBar(Vertical); WMenuBarPopup *p; p=mb->addItem("menu1"); p->addItem("menuItem1"); p->addItem("menuItem2"); p=mb->addItem("menu2"); p->addItem("menuItem3"); p->addItem("menuItem4"); hbox_ = new WHBoxLayout(root()); hbox_->addWidget(mb,1); } }; Wt::WApplication *createApplication(const Wt::WEnvironment& env) { Wt::WApplication *app = new ScheduleApplication(env); Wt::WCssDecorationStyle menuLabelStyle; menuLabelStyle.font().setSize(Wt::WFont::Small); app->styleSheet().addRule("ul.menu", menuLabelStyle); app->styleSheet().addRule("ul.menu", "width:auto;"); return app; } /* ./WebSchedule --http-address 127.0.0.1 --http-port 8080 --docroot . */ int main(int argc, char **argv) { return Wt::WRun(argc, argv, &createApplication); }
Makefile
Description: Binary data
Reading: /etc/wt/wt_config.xml
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100330
Fedora/3.5.9-1.fc11 Firefox/3.5.9
127.0.0.1 - - [2011-Mar-27 08:28:32.622424] "GET / HTTP/1.1" 200 1670
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100330
Fedora/3.5.9-1.fc11 Firefox/3.5.9
127.0.0.1 - - [2011-Mar-27 08:28:32.627218] "POST /?wtd=9g0PtdDcCJdkzEqE
HTTP/1.1" 200 49
id=oaokmkp
id=oaokml2
127.0.0.1 - - [2011-Mar-27 08:28:32.659946] "GET
/?wtd=bweOWpnyi3rahNW1&request=style HTTP/1.1" 200 113
127.0.0.1 - - [2011-Mar-27 08:28:32.668230] "GET
/?wtd=bweOWpnyi3rahNW1&request=script&rand=1944298466 HTTP/1.1" 200 31797
127.0.0.1 - - [2011-Mar-27 08:28:32.761664] "POST /?wtd=bweOWpnyi3rahNW1
HTTP/1.1" 200 41
entering mouseOver oaokmkp
leaving mouseOver oaokmkp
127.0.0.1 - - [2011-Mar-27 08:28:43.579016] "POST /?wtd=bweOWpnyi3rahNW1
HTTP/1.1" 200 41
entering mouseDown oaokmkp
hiding popup oaokmkr
hiding popup oaokml4
showing oaokmkp
selecting popup oaokmkr
127.0.0.1 - - [2011-Mar-27 08:28:44.406786] "POST /?wtd=bweOWpnyi3rahNW1
HTTP/1.1" 200 507
############################ case 2: this is the bad case
mouseOut oaokmkp
127.0.0.1 - - [2011-Mar-27 08:28:46.598742] "POST /?wtd=bweOWpnyi3rahNW1
HTTP/1.1" 200 41
entering mouseOver oaokml2
hiding oaokmkp
hiding popup oaokmkr
showing oaokml2
selecting popup oaokml4
leaving mouseOver oaokml2
mouseOut oaokml2
entering mouseOver oaokmkp
hiding oaokml2
hiding popup oaokml4
showing oaokmkp
selecting popup oaokmkr
leaving mouseOver oaokmkp
mouseOut oaokmkp
127.0.0.1 - - [2011-Mar-27 08:28:51.730720] "POST /?wtd=bweOWpnyi3rahNW1
HTTP/1.1" 200 539
############################ case 1: this is the good case
entering mouseOver oaokml2
hiding oaokmkp
hiding popup oaokmkr
showing oaokml2
selecting popup oaokml4
leaving mouseOver oaokml2
127.0.0.1 - - [2011-Mar-27 08:28:58.594424] "POST /?wtd=bweOWpnyi3rahNW1
HTTP/1.1" 200 515
mouseOut oaokml2
entering mouseOver oaokmkp
hiding oaokml2
hiding popup oaokml4
showing oaokmkp
selecting popup oaokmkr
leaving mouseOver oaokmkp
127.0.0.1 - - [2011-Mar-27 08:28:58.946487] "POST /?wtd=bweOWpnyi3rahNW1
HTTP/1.1" 200 517
mouseOut oaokmkp
127.0.0.1 - - [2011-Mar-27 08:28:59.274087] "POST /?wtd=bweOWpnyi3rahNW1
HTTP/1.1" 200 41
mouseUp oaokmkp
127.0.0.1 - - [2011-Mar-27 08:29:04.387629] "POST /?wtd=bweOWpnyi3rahNW1
HTTP/1.1" 200 41
------------------------------------------------------------------------------ Enable your software for Intel(R) Active Management Technology to meet the growing manageability and security demands of your customers. Businesses are taking advantage of Intel(R) vPro (TM) technology - will your software be a part of the solution? Download the Intel(R) Manageability Checker today! http://p.sf.net/sfu/intel-dev2devmar
_______________________________________________ witty-interest mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/witty-interest
