Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
webgui: introduce modified counter in ROOT7 TCanvas
Each call to TCanvas::Modified() increments modify counter. 
This counter used in then next TCanvas::Update() call to identify
current version of canvas. TCanvas::IsModified() will return true 
until drawing is completed and painter confirms that last version of
canvas delivered to all clients and displayed.
  • Loading branch information
linev committed Jul 26, 2017
commit a1225ab9ab0d2d2de9f1a2e0f1aff0593000b9ab
15 changes: 9 additions & 6 deletions graf2d/gpad/v7/inc/ROOT/TCanvas.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ private:
/// Title of the canvas.
std::string fTitle;

/// If canvas modified.
bool fModified;
uint64_t fModified; //<! increment counter when canvas modified.

/// The painter of this canvas, bootstrapping the graphics connection.
/// Unmapped canvases (those that never had `Draw()` invoked) might not have
Expand Down Expand Up @@ -126,17 +125,21 @@ public:
/// Remove an object from the list of primitives.
// TODO: void Wipe();

void Modified() { fModified = true; }

/// Actually display the canvas.
void Show();

/// Save canvas in image file
void SaveAs(const std::string &filename);
// Indicates that any object was modified
void Modified();

// Return if canvas was modified and not yet updated
bool IsModified() const;

/// update drawing
void Update();

/// Save canvas in image file
void SaveAs(const std::string &filename);

/// Get the canvas's title.
const std::string &GetTitle() const { return fTitle; }

Expand Down
6 changes: 6 additions & 0 deletions graf2d/gpad/v7/inc/ROOT/TVirtualCanvasPainter.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ public:
/// add display item to the canvas
virtual void AddDisplayItem(TDisplayItem *item) = 0;

/// indicate that canvas changed, provides current version of the canvas
virtual void CanvasUpdated(uint64_t) = 0;

/// return true if canvas modified since last painting
virtual bool IsCanvasModified(uint64_t) const = 0;

/// perform special action when drawing is ready
virtual void DoWhenReady(const std::string &, const std::string &) = 0;

Expand Down
24 changes: 22 additions & 2 deletions graf2d/gpad/v7/src/TCanvas.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,21 @@ const std::vector<std::shared_ptr<ROOT::Experimental::TCanvas>> &ROOT::Experimen
// }
// }

void ROOT::Experimental::TCanvas::Modified()
{
fModified++;
}

bool ROOT::Experimental::TCanvas::IsModified() const
{
return fPainter ? fPainter->IsCanvasModified(fModified) : fModified;
}

void ROOT::Experimental::TCanvas::Update()
{
if (fPainter)
fPainter->CanvasUpdated(fModified);

// SnapshotList_t lst;
// for (auto&& drw: fPrimitives) {
// TSnapshot *snap = drw->CreateSnapshot(*this);
Expand All @@ -62,14 +75,21 @@ std::shared_ptr<ROOT::Experimental::TCanvas> ROOT::Experimental::TCanvas::Create

void ROOT::Experimental::TCanvas::Show()
{
if (fPainter) return;
if (fPainter)
return;
bool batch_mode = gROOT->IsBatch();
if (!fModified)
fModified = 1; // 0 is special value, means no changes and no drawings

fPainter = Internal::TVirtualCanvasPainter::Create(*this, batch_mode);
if (fPainter)
fPainter->CanvasUpdated(fModified);
}

void ROOT::Experimental::TCanvas::SaveAs(const std::string &filename)
{
if (!fPainter) fPainter = Internal::TVirtualCanvasPainter::Create(*this, true);
if (!fPainter)
fPainter = Internal::TVirtualCanvasPainter::Create(*this, true);
if (filename.find(".svg") != std::string::npos)
fPainter->DoWhenReady("SVG", filename);
else if (filename.find(".png") != std::string::npos)
Expand Down
83 changes: 63 additions & 20 deletions gui/canvaspainter/v7/src/TCanvasPainter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,12 @@ class TCanvasPainter : public THttpWSHandler,
private:
struct WebConn {
THttpWSEngine *fHandle; ///<! websocket handle
Bool_t fReady; ///!< when connection ready to send new data
Bool_t fDrawReady; ///!< when first drawing is performed
bool fReady; ///!< when connection ready to send new data
bool fDrawReady; ///!< when first drawing is performed
std::string fGetMenu; ///<! object id for menu request
Bool_t fModified; ///<! indicates if canvas was modified for that connection
WebConn() : fHandle(0), fReady(kFALSE), fDrawReady(kFALSE), fGetMenu(), fModified(kFALSE) {}
uint64_t fSend; ///<! indicates version send to connection
uint64_t fDelivered; ///<! indicates version confirmed from canvas
WebConn() : fHandle(0), fReady(false), fDrawReady(false), fGetMenu(), fSend(0), fDelivered(0) {}
};

typedef std::list<WebConn> WebConnList;
Expand All @@ -184,6 +185,10 @@ class TCanvasPainter : public THttpWSHandler,
ROOT::Experimental::TPadDisplayItem fDisplayList; ///!< full list of items to display
std::string fNextCmd; ///!< command which will be executed next

uint64_t fSnapshotVersion; ///!< version of snapshot
std::string fSnapshot; ///!< last produced snapshot
uint64_t fSnapshotDelivered; ///!< minimal version delivered to all connections

static std::string fAddr; ///<! real http address (when assigned)
static THttpServer *gServer; ///<! server

Expand All @@ -197,7 +202,7 @@ class TCanvasPainter : public THttpWSHandler,

void CreateHttpServer(Bool_t with_http = kFALSE);
void PopupBrowser();
void CheckModifiedFlag();
void CheckDataToSend();
std::string CreateSnapshot(const ROOT::Experimental::TCanvas &can);

/// Send the canvas primitives to the THttpServer.
Expand All @@ -209,7 +214,8 @@ class TCanvasPainter : public THttpWSHandler,
/// Create a TVirtualCanvasPainter for the given canvas.
/// The painter observes it; it needs to know should the TCanvas be deleted.
TCanvasPainter(const std::string &name, const ROOT::Experimental::TCanvas &canv, bool batch_mode)
: THttpWSHandler(name.c_str(), "title"), fCanvas(canv), fBatchMode(batch_mode), fWebConn()
: THttpWSHandler(name.c_str(), "title"), fCanvas(canv), fBatchMode(batch_mode), fWebConn(), fDisplayList(),
fNextCmd(), fSnapshotVersion(0), fSnapshot(), fSnapshotDelivered(0)
{
CreateHttpServer();
gServer->Register("/web7gui", this);
Expand All @@ -220,6 +226,10 @@ class TCanvasPainter : public THttpWSHandler,

virtual void AddDisplayItem(ROOT::Experimental::TDisplayItem *item) final;

virtual void CanvasUpdated(uint64_t) override;

virtual bool IsCanvasModified(uint64_t) const override;

/// perform special action when drawing is ready
virtual void DoWhenReady(const std::string &cmd, const std::string &arg) final;

Expand Down Expand Up @@ -340,10 +350,20 @@ void TCanvasPainter::PopupBrowser()
gSystem->Exec(exec);
}

void TCanvasPainter::CanvasUpdated(uint64_t ver)
{
fSnapshotVersion = ver;
fSnapshot = CreateSnapshot(fCanvas);

printf("Created snapshot %lu len %d\n", ver, (int)fSnapshot.length());

CheckDataToSend();
}

void TCanvasPainter::DoWhenReady(const std::string &cmd, const std::string &arg)
{
fNextCmd = cmd + ":" + arg;
CheckModifiedFlag();
CheckDataToSend();
}

Bool_t TCanvasPainter::ProcessWS(THttpCallArg *arg)
Expand Down Expand Up @@ -377,10 +397,11 @@ Bool_t TCanvasPainter::ProcessWS(THttpCallArg *arg)

WebConn newconn;
newconn.fHandle = wshandle;
newconn.fModified = kTRUE;

fWebConn.push_back(newconn);
printf("socket is ready\n");
printf("socket is ready %d\n", fWebConn.back().fReady);

CheckDataToSend();

return kTRUE;
}
Expand Down Expand Up @@ -416,15 +437,20 @@ Bool_t TCanvasPainter::ProcessWS(THttpCallArg *arg)

if (strncmp(cdata, "READY", 5) == 0) {
conn->fReady = kTRUE;
CheckModifiedFlag();
CheckDataToSend();
} else if (strncmp(cdata, "SNAPDONE:", 9) == 0) {
conn->fReady = kTRUE;
conn->fDrawReady = kTRUE; // at least first drawing is performed
conn->fDelivered = (uint64_t)TString(cdata + 9).Atoll(); // delivered version of the snapshot
CheckDataToSend();
} else if (strncmp(cdata, "RREADY:", 7) == 0) {
conn->fReady = kTRUE;
conn->fDrawReady = kTRUE; // at least first drawing is performed
CheckModifiedFlag();
CheckDataToSend();
} else if (strncmp(cdata, "GETMENU:", 8) == 0) {
conn->fReady = kTRUE;
conn->fGetMenu = cdata + 8;
CheckModifiedFlag();
CheckDataToSend();
} else if (strncmp(cdata, "GEXE:", 5) == 0) {
// TODO: temporary solution, should be removed later
// used now to terminate ROOT session
Expand All @@ -441,7 +467,7 @@ Bool_t TCanvasPainter::ProcessWS(THttpCallArg *arg)
printf("Create SVG file %s len %d\n", fname.Data(), buf.Length());
}
conn->fReady = kTRUE;
CheckModifiedFlag();
CheckDataToSend();
} else if (strncmp(cdata, "DONEPNG:", 8) == 0) {
TString buf(cdata + 8);
Int_t pos = buf.First(':');
Expand All @@ -459,7 +485,7 @@ Bool_t TCanvasPainter::ProcessWS(THttpCallArg *arg)
printf("Error when producing PNG image %s\n", buf.Data());
}
conn->fReady = kTRUE;
CheckModifiedFlag();
CheckDataToSend();
} else if (strncmp(cdata, "OBJEXEC:", 8) == 0) {
TString buf(cdata + 8);
Int_t pos = buf.First(':');
Expand All @@ -478,12 +504,17 @@ Bool_t TCanvasPainter::ProcessWS(THttpCallArg *arg)
return kTRUE;
}

void TCanvasPainter::CheckModifiedFlag()
void TCanvasPainter::CheckDataToSend()
{

uint64_t min_delivered = 0;

for (WebConnList::iterator citer = fWebConn.begin(); citer != fWebConn.end(); ++citer) {
WebConn &conn = *citer;

if (conn.fDelivered && (!min_delivered || (min_delivered < conn.fDelivered)))
min_delivered = conn.fDelivered;

if (!conn.fReady || !conn.fHandle)
continue;

Expand All @@ -509,13 +540,15 @@ void TCanvasPainter::CheckModifiedFlag()
}

conn.fGetMenu = "";
} else if (conn.fModified) {
} else if (conn.fSend != fSnapshotVersion) {
// buf = "JSON";
// buf += TBufferJSON::ConvertToJSON(Canvas(), 3);

buf = "SNAP";
buf += CreateSnapshot(fCanvas);
conn.fModified = kFALSE;
conn.fSend = fSnapshotVersion;
buf = "SNAP:";
buf += TString::ULLtoa(fSnapshotVersion, 10);
buf += ":";
buf += fSnapshot;
}

if (buf.Length() > 0) {
Expand All @@ -524,6 +557,16 @@ void TCanvasPainter::CheckModifiedFlag()
conn.fHandle->SendCharStar(buf.Data());
}
}

if (fSnapshotDelivered != min_delivered) {
fSnapshotDelivered = min_delivered;
// one could call-back canvas methods here
}
}

bool TCanvasPainter::IsCanvasModified(uint64_t id) const
{
return fSnapshotDelivered != id;
}

void TCanvasPainter::AddDisplayItem(ROOT::Experimental::TDisplayItem *item)
Expand Down Expand Up @@ -551,7 +594,7 @@ std::string TCanvasPainter::CreateSnapshot(const ROOT::Experimental::TCanvas &ca

fDisplayList.SetObjectIDAsPtr((void *)&can);

TPad *dummy = new TPad(); // just to keep information we need for different ranges now
TPad *dummy = new TPad(); // just provide old class where all kind of info (size, ranges) already provided

auto *snap = new ROOT::Experimental::TUniqueDisplayItem<TPad>(dummy);
snap->SetObjectIDAsPtr((void *)&can);
Expand Down