Bug #3229
closed3 problems with WCssStyleSheet
0%
Description
I found 3 problems while trying to send changes to WCssStyleSheet. All 3 problems can be reproduced with the C file and config file included. I simply edited hello.C.
I also included a function to post new WText widget to all open sessions to test if push is working properly.
1. WServer::post() WCssStyleSheet changes do not get pushed. Only the session that sent the changes is successfully updated.¶
To reproduce
- Compile with bool USE_INLINE_WCSSSTYLESHEET = true;
- Open 2 or more sessions, use any combination of browsers(I used Chrome, Firefox and Safari iOS)
Press the 'toggle styleSheet() rules' button
You will see that the session that you clicked the button from will be updated perfectly, however, the other open sessions gets the changes post()ed, however, the are not 'pushed' to the browser. If you refresh the session from the browser refresh button, first the page will, for a fraction of a second, change color but it will go back to white. If you refresh again then only the changes will become permanent.
2. External stylesheets do not link properly after a refresh¶
To reproduce
- Compile with bool USE_INLINE_WCSSSTYLESHEET = false;
- Open a session
Press the browser refresh button
You will that the html has a background colour, however, after you refresh the page the background colour will be gone and it'll be plain white.
3. Problem clearing/deleting CssRules from UserStyleSheet¶
To reproduce
- Compile with bool USE_INLINE_WCSSSTYLESHEET = false;
- Open 2 or more sessions
- Press the 'toggle styleSheet() rules' two times
I get an unhandled exception error in 'void WCssStyleSheet::clear()' 2nd line 'delete rules_.back();'
wt_config.xml
<server>
<application-settings location="*">
<session-management>
<tracking>URL</tracking>
<reload-is-new-session>false</reload-is-new-session>
</session-management>
<log-config>* -debug -info</log-config>
</application-settings>
</server>
hello.C
#include <Wt/WApplication>
#include <Wt/WBreak>
#include <Wt/WContainerWidget>
#include <Wt/WPushButton>
#include <Wt/WServer>
#include <Wt/WCssStyleSheet>
using namespace Wt;
bool USE_INLINE_WCSSSTYLESHEET = false;
class HelloApplication : public WApplication
{
public:
HelloApplication(const WEnvironment& env);
~HelloApplication();
void ResetCssRules(WCssTextRule *rule);
void Listen(const std::string &sessionId);
private:
bool S;
WCssStyleSheet UserStyleSheet;
};
typedef std::set<HelloApplication *> AppSetType;
AppSetType AppSet;
HelloApplication::HelloApplication(const WEnvironment& env)
: WApplication(env), S(false)
{
setTitle("WCssStyleSheet update test");
//initial html css rule
if(USE_INLINE_WCSSSTYLESHEET)
styleSheet().addRule(new WCssTextRule("html", "background:#FFEE00;"));
else
UserStyleSheet.addRule(new WCssTextRule("html", "background:#FFEE00;"));
useStyleSheet(UserStyleSheet);
auto button = new WPushButton("Toggle styleSheet() rules", root());
button->setFocus();
button->clicked().connect(boost::bind<void>([this](){
WCssTextRule *NewCssRule;
if(S)
{
NewCssRule = new WCssTextRule("html", "background:#FFEE00;");
}
else
{
NewCssRule = new WCssTextRule("html", "background:#123456;");
}
for(AppSetType::iterator itr = AppSet.begin();
itr != AppSet.end();
++itr)
{
if(*itr == this) //Call function directly if its the same app
ResetCssRules(NewCssRule);
else
WServer::instance()->post((*itr)->sessionId(), boost::bind(&HelloApplication::ResetCssRules, *itr, NewCssRule));
}
S = !S;
}));
auto sayHiButton = new WPushButton("Say Hi to every one", root());
sayHiButton->clicked().connect(boost::bind<void>([this](){
for(AppSetType::iterator itr = AppSet.begin();
itr != AppSet.end();
++itr)
{
if(*itr == this) //Call function directly if its the same app
Listen(sessionId());
else
WServer::instance()->post((*itr)->sessionId(), boost::bind(&HelloApplication::Listen, *itr, sessionId()));
}
}));
//I use mutex, but I don't believe it would be a problem for testing
AppSet.insert(this);
enableUpdates();
}
HelloApplication::~HelloApplication()
{
//I use mutex, but I don't believe it would be a problem for testing
AppSet.erase(this);
}
void HelloApplication::ResetCssRules(WCssTextRule *rule)
{
if(USE_INLINE_WCSSSTYLESHEET)
{
styleSheet().clear();
styleSheet().addRule(rule);
}
else
{
UserStyleSheet.clear();
UserStyleSheet.addRule(rule);
}
triggerUpdate();
}
void HelloApplication::Listen(const std::string &sessionId)
{
new WBreak(root());
new WText(std::string("Session ") + sessionId + " said hi", root());
triggerUpdate();
}
WApplication *createApplication(const WEnvironment& env)
{
return new HelloApplication(env);
}
int main(int argc, char **argv)
{
return WRun(argc, argv, &createApplication);
}
Files
Updated by Saif Rehman almost 11 years ago
Actually the flicker of background color to white does not occur on Safari iOS
Updated by Koen Deforche almost 11 years ago
- Status changed from New to InProgress
- Assignee set to Michael Vilsker
Updated by Michael Vilsker almost 11 years ago
- File 3229.patch 3229.patch added
Hello Saif,
Thank you for this bug report.
1. That really is a bug. You may use the attached patch or wait for the next release.
- useStyleSheet() works only with StyleSheet that have valid link. Use useStyleSheet(WLink(...))
You may not use same WCssTextRule in many applications.
use:std::string newCssRuleStr = S ? "background:#FFEE00;" :
"background:#123456;";for(AppSetType::iterator itr = AppSet.begin(); itr != AppSet.end(); ++itr) { if(*itr == this) //Call function directly if its the same app ResetCssRules(new WCssTextRule("html", newCssRuleStr)); else WServer::instance()->post( (*itr)->sessionId(), boost::bind(&HelloApplication::ResetCssRules, *itr, new WCssTextRule("html", newCssRuleStr))); }
Updated by Michael Vilsker almost 11 years ago
- Status changed from InProgress to Resolved
Updated by Saif Rehman almost 11 years ago
Thanks for the fix.
In (2), does that mean we can't create inline CSS using useStyleSheet(). I would rather not reset the default WApplication's stylesheet since it has Wt's default css rules.
In (1), is it up on git or should I use the patch instead?
Updated by Koen Deforche almost 11 years ago
Hey Saif,
(2) means that you can use the inline css stylesheet, but you should consider it as a facility to create dynamic CSS rules (this is also how it is being used in Wt from e.g. WTableView and WTreeView). What's your use-case for this and would an external stylesheet not be more practical --- you can also dynamically generate an external stylesheet using a WResource.
(1) is not yet pushed to git, I'll probably do that today.
Regards,
koen
Updated by Saif Rehman almost 11 years ago
That's weird because the problem had been fixed when I checked it 5 days ago
Updated by Koen Deforche almost 11 years ago
Hey Saif,
Ah, it hijacked then another fix which I pushed!
Koen
Updated by Koen Deforche over 10 years ago
- Status changed from Resolved to Closed