Project

General

Profile

Actions

Bug #3229

closed

3 problems with WCssStyleSheet

Added by Saif Rehman almost 10 years ago. Updated over 9 years ago.

Status:
Closed
Priority:
High
Assignee:
Michael Vilsker
Target version:
-
Start date:
05/30/2014
Due date:
% Done:

0%

Estimated time:

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

  1. Compile with bool USE_INLINE_WCSSSTYLESHEET = true;
  2. Open 2 or more sessions, use any combination of browsers(I used Chrome, Firefox and Safari iOS)
  3. 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

  1. Compile with bool USE_INLINE_WCSSSTYLESHEET = false;
  2. Open a session
  3. 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

  1. Compile with bool USE_INLINE_WCSSSTYLESHEET = false;
  2. Open 2 or more sessions
  3. 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

3229.patch (2.6 KB) 3229.patch Michael Vilsker, 06/12/2014 06:45 PM
Actions #1

Updated by Saif Rehman almost 10 years ago

Actually the flicker of background color to white does not occur on Safari iOS

Actions #2

Updated by Koen Deforche almost 10 years ago

  • Status changed from New to InProgress
  • Assignee set to Michael Vilsker
Actions #3

Updated by Michael Vilsker almost 10 years ago

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.

  1. useStyleSheet() works only with StyleSheet that have valid link. Use useStyleSheet(WLink(...))
  2. 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)));
      }
    
Actions #4

Updated by Michael Vilsker almost 10 years ago

  • Status changed from InProgress to Resolved
Actions #5

Updated by Saif Rehman almost 10 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?

Actions #6

Updated by Koen Deforche almost 10 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

Actions #7

Updated by Saif Rehman almost 10 years ago

That's weird because the problem had been fixed when I checked it 5 days ago

Actions #8

Updated by Koen Deforche almost 10 years ago

Hey Saif,

Ah, it hijacked then another fix which I pushed!

Koen

Actions #9

Updated by Koen Deforche over 9 years ago

  • Status changed from Resolved to Closed
Actions

Also available in: Atom PDF