diff --git a/graf2d/gpad/inc/TPadPainter.h b/graf2d/gpad/inc/TPadPainter.h index 89ac417f9a57c..590d32068da25 100644 --- a/graf2d/gpad/inc/TPadPainter.h +++ b/graf2d/gpad/inc/TPadPainter.h @@ -24,6 +24,7 @@ class TVirtualPad; class TPadPainter : public TPadPainterBase { WinContext_t fWinContext; + Int_t fDoubleBuffer; public: TPadPainter(); @@ -46,6 +47,7 @@ class TPadPainter : public TPadPainterBase { void SelectDrawable(Int_t device) override; void UpdateDrawable(Int_t mode) override; void SetDrawMode(Int_t device, Int_t mode) override; + void SetDoubleBuffer(Int_t device, Int_t mode) override; //TASImage support (noop for a non-gl pad). diff --git a/graf2d/gpad/src/TCanvas.cxx b/graf2d/gpad/src/TCanvas.cxx index 25964427aaf91..3e6a550b2d705 100644 --- a/graf2d/gpad/src/TCanvas.cxx +++ b/graf2d/gpad/src/TCanvas.cxx @@ -1262,7 +1262,7 @@ void TCanvas::HandleInput(EEventType event, Int_t px, Int_t py) case kMouseEnter: // mouse enters canvas - if (!fDoubleBuffer) FeedbackMode(kTRUE); + //FeedbackMode(kTRUE); break; case kMouseLeave: @@ -1276,7 +1276,7 @@ void TCanvas::HandleInput(EEventType event, Int_t px, Int_t py) EnterLeave(prevSelPad, prevSelObj); fSelected = sobj; fSelectedPad = spad; - if (!fDoubleBuffer) FeedbackMode(kFALSE); + //FeedbackMode(kFALSE); } break; diff --git a/graf2d/gpad/src/TPad.cxx b/graf2d/gpad/src/TPad.cxx index c1272454b597b..3a858128f869f 100644 --- a/graf2d/gpad/src/TPad.cxx +++ b/graf2d/gpad/src/TPad.cxx @@ -1950,35 +1950,27 @@ void TPad::DrawColorTable() void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) { - const Int_t kMaxDiff = 5; - const Int_t kMinSize = 20; - static Int_t pxorg, pyorg; - static Int_t px1, px2, py1, py2, pxl, pyl, pxt, pyt, pxold, pyold; - static Int_t px1p, px2p, py1p, py2p, pxlp, pylp, pxtp, pytp; - static Bool_t pA, pB, pC, pD, pTop, pL, pR, pBot, pINSIDE; - Int_t wx, wy; + constexpr Int_t kMaxDiff = 5; + constexpr Int_t kMinSize = 20; + static Int_t px1, px2, py1, py2, dpx1, dpy2; + static Int_t px1p, px2p, py1p, py2p; + static enum { pNone, pA, pB, pC, pD, pTop, pL, pR, pBot, pINSIDE } mode = pNone; + static Bool_t firstPaint = kFALSE; Bool_t opaque = OpaqueMoving(); Bool_t ropaque = OpaqueResizing(); - Bool_t fixedr = HasFixedAspectRatio(); if (!IsEditable() && event != kMouseEnter) return; - TVirtualPad *parent = GetMother(); - if (!parent->IsEditable()) return; + TVirtualPad &parent = *GetMother(); + if (!parent.IsEditable()) return; HideToolTip(event); if (fXlowNDC < 0 && event != kButton1Down) return; if (fYlowNDC < 0 && event != kButton1Down) return; - // keep old mouse position - if (event == kButton1Down) { - pxorg = px; - pyorg = py; - } - Int_t newcode = gROOT->GetEditorMode(); if (newcode) - pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE; + mode = pNone; switch (newcode) { case kPad: TCreatePrimitives::Pad(event,px,py,0); @@ -2025,21 +2017,18 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) if (newcode) return; - auto pp = GetPainter(); - - auto action = [this,pp,parent](Bool_t paint, Int_t _x1, Int_t _y1, Int_t _x2, Int_t _y2) { - auto x1 = AbsPixeltoX(_x1); - auto y1 = AbsPixeltoY(_y1); - auto x2 = AbsPixeltoX(_x2); - auto y2 = AbsPixeltoY(_y2); - if (paint) { - pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow); - } else { + auto paint_or_set = [this, &parent](Bool_t paint) + { + auto x1 = AbsPixeltoX(px1); + auto y1 = AbsPixeltoY(py1); + auto x2 = AbsPixeltoX(px2); + auto y2 = AbsPixeltoY(py2); + if (!paint) { // Get parent corners pixels coordinates - Int_t parentpx1 = fMother->XtoAbsPixel(parent->GetX1()); - Int_t parentpx2 = fMother->XtoAbsPixel(parent->GetX2()); - Int_t parentpy1 = fMother->YtoAbsPixel(parent->GetY1()); - Int_t parentpy2 = fMother->YtoAbsPixel(parent->GetY2()); + Int_t parentpx1 = fMother->XtoAbsPixel(parent.GetX1()); + Int_t parentpx2 = fMother->XtoAbsPixel(parent.GetX2()); + Int_t parentpy1 = fMother->YtoAbsPixel(parent.GetY1()); + Int_t parentpy2 = fMother->YtoAbsPixel(parent.GetY2()); // Get pad new corners pixels coordinates Int_t apx1 = XtoAbsPixel(x1); if (apx1 < parentpx1) {apx1 = parentpx1; } @@ -2052,7 +2041,48 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) fYlowNDC = Double_t(apy1 - parentpy1)/Double_t(parentpy2 - parentpy1); fWNDC = Double_t(apx2 - apx1)/Double_t(parentpx2 - parentpx1); fHNDC = Double_t(apy2 - apy1)/Double_t(parentpy2 - parentpy1); + } else if (firstPaint) { + // first paint with original coordinates not required + firstPaint = kFALSE; + } else { + auto pp = GetPainter(); + pp->SetAttLine({GetFillColor() > 0 ? GetFillColor() : (Color_t) 1, GetLineStyle(), 2}); + pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow); + } + }; + + Int_t prevpx1 = px1, prevpx2 = px2, prevpy1 = py1, prevpy2 = py2; + + // function check how to restore pad ratio + auto adjustRatio = [this, &parent](int choise = 11) -> bool + { + if (!HasFixedAspectRatio()) + return true; // do nothing + + if (choise == 11) { + Int_t dx = parent.UtoPixel(fAspectRatio * (py1 - py2) / parent.VtoPixel(0)); + Int_t npx1 = (px1 + px2) / 2 - dx / 2; + Int_t npx2 = npx1 + dx; + if ((npx1 >= px1p) && (npx2 <= px2p)) { + px1 = npx1; px2 = npx2; + return true; + } + } else { + Int_t dy = parent.VtoPixel(1. - (0. + px2 - px1) / parent.UtoPixel(1.) / fAspectRatio); + Int_t npy1 = py1; + Int_t npy2 = py2; + switch (choise) { + case -1: npy2 = py1 - dy; break; + case 0: npy2 = (py1 + py2) / 2 - dy / 2; npy1 = npy2 + dy; break; + case 1: npy1 = py2 + dy; break; + } + if ((npy1 <= py1p) && (npy2 >= py2p)) { + py1 = npy1; py2 = npy2; + return true; + } } + + return false; // fail to adjust ratio, need to restore values }; switch (event) { @@ -2067,7 +2097,6 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) fXUpNDC = fXlowNDC + fWNDC; fYUpNDC = fYlowNDC + fHNDC; - pp->SetAttLine({GetFillColor() > 0 ? GetFillColor() : (Color_t) 1, GetLineStyle(), 2}); // No break !!! @@ -2078,100 +2107,63 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) px2 = XtoAbsPixel(fX2); py2 = YtoAbsPixel(fY2); - if (px1 < px2) { - pxl = px1; - pxt = px2; - } else { - pxl = px2; - pxt = px1; - } - if (py1 < py2) { - pyl = py1; - pyt = py2; - } else { - pyl = py2; - pyt = py1; - } + if (px1 > px2) + std::swap(px1, px2); - px1p = parent->XtoAbsPixel(parent->GetX1()) + parent->GetBorderSize(); - py1p = parent->YtoAbsPixel(parent->GetY1()) - parent->GetBorderSize(); - px2p = parent->XtoAbsPixel(parent->GetX2()) - parent->GetBorderSize(); - py2p = parent->YtoAbsPixel(parent->GetY2()) + parent->GetBorderSize(); + if (py1 < py2) + std::swap(py1, py2); - if (px1p < px2p) { - pxlp = px1p; - pxtp = px2p; - } else { - pxlp = px2p; - pxtp = px1p; - } - if (py1p < py2p) { - pylp = py1p; - pytp = py2p; - } else { - pylp = py2p; - pytp = py1p; - } + px1p = parent.XtoAbsPixel(parent.GetX1()) + parent.GetBorderSize(); + py1p = parent.YtoAbsPixel(parent.GetY1()) - parent.GetBorderSize(); + px2p = parent.XtoAbsPixel(parent.GetX2()) - parent.GetBorderSize(); + py2p = parent.YtoAbsPixel(parent.GetY2()) + parent.GetBorderSize(); - pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE; + if (px1p > px2p) + std::swap(px1p, px2p); - // case pA - if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) { - pxold = pxl; pyold = pyl; pA = kTRUE; + if (py1p < py2p) + std::swap(py1p, py2p); + + mode = pNone; + if (TMath::Abs(px - px1) <= kMaxDiff && TMath::Abs(py - py2) <= kMaxDiff) { + mode = pA; SetCursor(kTopLeft); - } - // case pB - if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) { - pxold = pxt; pyold = pyl; pB = kTRUE; + } else if (TMath::Abs(px - px2) <= kMaxDiff && TMath::Abs(py - py2) <= kMaxDiff) { + mode = pB; SetCursor(kTopRight); - } - // case pC - if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) { - pxold = pxt; pyold = pyt; pC = kTRUE; + } else if (TMath::Abs(px - px2) <= kMaxDiff && TMath::Abs(py - py1) <= kMaxDiff) { + mode = pC; SetCursor(kBottomRight); - } - // case pD - if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) { - pxold = pxl; pyold = pyt; pD = kTRUE; + } else if (TMath::Abs(px - px1) <= kMaxDiff && TMath::Abs(py - py1) <= kMaxDiff) { + mode = pD; SetCursor(kBottomLeft); - } - - if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) && - TMath::Abs(py - pyl) < kMaxDiff) { // top edge - pxold = pxl; pyold = pyl; pTop = kTRUE; + } else if ((px > px1 + kMaxDiff && px < px2 - kMaxDiff) && TMath::Abs(py - py2) < kMaxDiff) { + mode = pTop; SetCursor(kTopSide); - } - - if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) && - TMath::Abs(py - pyt) < kMaxDiff) { // bottom edge - pxold = pxt; pyold = pyt; pBot = kTRUE; + } else if ((px > px1 + kMaxDiff && px < px2 - kMaxDiff) && TMath::Abs(py - py1) < kMaxDiff) { + mode = pBot; SetCursor(kBottomSide); - } - - if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) && - TMath::Abs(px - pxl) < kMaxDiff) { // left edge - pxold = pxl; pyold = pyl; pL = kTRUE; + } else if ((py > py2 + kMaxDiff && py < py1 - kMaxDiff) && TMath::Abs(px - px1) < kMaxDiff) { + mode = pL; SetCursor(kLeftSide); - } - - if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) && - TMath::Abs(px - pxt) < kMaxDiff) { // right edge - pxold = pxt; pyold = pyt; pR = kTRUE; + } else if ((py > py2 + kMaxDiff && py < py1 - kMaxDiff) && TMath::Abs(px - px2) < kMaxDiff) { + mode = pR; SetCursor(kRightSide); - } - - if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) && - (py > pyl+kMaxDiff && py < pyt-kMaxDiff)) { // inside box - pxold = px; pyold = py; pINSIDE = kTRUE; + } else if ((px > px1+kMaxDiff && px < px2-kMaxDiff) && (py > py2+kMaxDiff && py < py1-kMaxDiff)) { + dpx1 = px - px1; // cursor position relative to top-left corner + dpy2 = py - py2; + mode = pINSIDE; if (event == kButton1Down) SetCursor(kMove); else SetCursor(kCross); } - fResizing = pA || pB || pC || pD || pTop || pL || pR || pBot; + fResizing = (mode != pNone) && (mode != pINSIDE); - if (!fResizing && !pINSIDE) + firstPaint = kTRUE; + + if (mode == pNone) SetCursor(kCross); break; @@ -2180,205 +2172,107 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) case kButton1Motion: if (TestBit(kCannotMove)) break; - wx = wy = 0; - - if (pA) { - if (!ropaque) action(kTRUE, pxold, pyt, pxt, pyold); - if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; } - if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; } - if (px < pxlp) { px = pxlp; wx = px; } - if (py < pylp) { py = pylp; wy = py; } - if (fixedr) { - Double_t dy = Double_t(TMath::Abs(pxt-px))/parent->UtoPixel(1.) / - fAspectRatio; - Int_t npy2 = pyt - TMath::Abs(parent->VtoAbsPixel(dy) - - parent->VtoAbsPixel(0)); - if (npy2 < pylp) { - px = pxold; - py = pyold; - } else - py = npy2; - - wx = wy = 0; - } - if (!ropaque) action(kTRUE, px, pyt, pxt, py); - } - if (pB) { - if (!ropaque) action(kTRUE, pxl, pyt, pxold, pyold); - if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; } - if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; } - if (px > pxtp) { px = pxtp; wx = px; } - if (py < pylp) { py = pylp; wy = py; } - if (fixedr) { - Double_t dy = Double_t(TMath::Abs(pxl-px))/parent->UtoPixel(1.) / - fAspectRatio; - Int_t npy2 = pyt - TMath::Abs(parent->VtoAbsPixel(dy) - - parent->VtoAbsPixel(0)); - if (npy2 < pylp) { - px = pxold; - py = pyold; - } else - py = npy2; - - wx = wy = 0; - } - if (!ropaque) action(kTRUE, pxl, pyt, px, py); - } - if (pC) { - if (!ropaque) action(kTRUE, pxl, pyl, pxold, pyold); - if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; } - if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; } - if (px > pxtp) { px = pxtp; wx = px; } - if (py > pytp) { py = pytp; wy = py; } - if (fixedr) { - Double_t dy = Double_t(TMath::Abs(pxl-px))/parent->UtoPixel(1.) / - fAspectRatio; - Int_t npy2 = pyl + TMath::Abs(parent->VtoAbsPixel(dy) - - parent->VtoAbsPixel(0)); - if (npy2 > pytp) { - px = pxold; - py = pyold; - } else - py = npy2; - - wx = wy = 0; - } - if (!ropaque) action(kTRUE, pxl, pyl, px, py); - } - if (pD) { - if (!ropaque) action(kTRUE, pxold, pyold, pxt, pyl); - if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; } - if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; } - if (px < pxlp) { px = pxlp; wx = px; } - if (py > pytp) { py = pytp; wy = py; } - if (fixedr) { - Double_t dy = Double_t(TMath::Abs(pxt-px))/parent->UtoPixel(1.) / - fAspectRatio; - Int_t npy2 = pyl + TMath::Abs(parent->VtoAbsPixel(dy) - - parent->VtoAbsPixel(0)); - if (npy2 > pytp) { - px = pxold; - py = pyold; - } else - py = npy2; - - wx = wy = 0; - } - if (!ropaque) action(kTRUE, px, py, pxt, pyl); - } - if (pTop) { - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - py2 += py - pyold; - if (py2 > py1-kMinSize) { py2 = py1-kMinSize; wy = py2; } - if (py2 < py2p) { py2 = py2p; wy = py2; } - if (fixedr) { - Double_t dx = Double_t(TMath::Abs(py2-py1))/parent->VtoPixel(0) * - fAspectRatio; - Int_t npx2 = px1 + parent->UtoPixel(dx); - if (npx2 > px2p) - py2 -= py - pyold; - else - px2 = npx2; - } - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - } - if (pBot) { - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - py1 += py - pyold; - if (py1 < py2+kMinSize) { py1 = py2+kMinSize; wy = py1; } - if (py1 > py1p) { py1 = py1p; wy = py1; } - if (fixedr) { - Double_t dx = Double_t(TMath::Abs(py2-py1))/parent->VtoPixel(0) * - fAspectRatio; - Int_t npx2 = px1 + parent->UtoPixel(dx); - if (npx2 > px2p) - py1 -= py - pyold; - else - px2 = npx2; + + switch (mode) { + case pNone: + return; + case pA: + if (!ropaque) paint_or_set(kTRUE); + px1 = TMath::Max(px1p, TMath::Min(px, px2 - kMinSize)); + py2 = TMath::Max(py2p, TMath::Min(py, py1 - kMinSize)); + if (!adjustRatio(-1)) { + px1 = prevpx1; + py2 = prevpy2; } - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - } - if (pL) { - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - px1 += px - pxold; - if (px1 > px2-kMinSize) { px1 = px2-kMinSize; wx = px1; } - if (px1 < px1p) { px1 = px1p; wx = px1; } - if (fixedr) { - Double_t dy = Double_t(TMath::Abs(px2-px1))/parent->UtoPixel(1.) / - fAspectRatio; - Int_t npy2 = py1 - TMath::Abs(parent->VtoAbsPixel(dy) - - parent->VtoAbsPixel(0)); - if (npy2 < py2p) - px1 -= px - pxold; - else - py2 = npy2; + paint_or_set(!ropaque); + break; + case pB: + if (!ropaque) paint_or_set(kTRUE); + px2 = TMath::Min(px2p, TMath::Max(px, px1 + kMinSize)); + py2 = TMath::Max(py2p, TMath::Min(py, py1 - kMinSize)); + if (!adjustRatio(-1)) { + px2 = prevpx2; + py2 = prevpy2; } - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - } - if (pR) { - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - px2 += px - pxold; - if (px2 < px1+kMinSize) { px2 = px1+kMinSize; wx = px2; } - if (px2 > px2p) { px2 = px2p; wx = px2; } - if (fixedr) { - Double_t dy = Double_t(TMath::Abs(px2-px1))/parent->UtoPixel(1.) / - fAspectRatio; - Int_t npy2 = py1 - TMath::Abs(parent->VtoAbsPixel(dy) - - parent->VtoAbsPixel(0)); - if (npy2 < py2p) - px2 -= px - pxold; - else - py2 = npy2; + paint_or_set(!ropaque); + break; + case pC: + if (!ropaque) paint_or_set(kTRUE); + px2 = TMath::Min(px2p, TMath::Max(px, px1 + kMinSize)); + py1 = TMath::Min(py1p, TMath::Max(py, py2 + kMinSize)); + if (!adjustRatio(1)) { + px2 = prevpx2; + py1 = prevpy1; } - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - } - if (pINSIDE) { - if (!opaque) action(kTRUE, px1, py1, px2, py2); // draw the old box - Int_t dx = px - pxold; - Int_t dy = py - pyold; - px1 += dx; py1 += dy; px2 += dx; py2 += dy; - if (px1 < px1p) { dx = px1p - px1; px1 += dx; px2 += dx; wx = px+dx; } - if (px2 > px2p) { dx = px2 - px2p; px1 -= dx; px2 -= dx; wx = px-dx; } - if (py1 > py1p) { dy = py1 - py1p; py1 -= dy; py2 -= dy; wy = py-dy; } - if (py2 < py2p) { dy = py2p - py2; py1 += dy; py2 += dy; wy = py+dy; } - if (!opaque) action(kTRUE, px1, py1, px2, py2); // draw the new box - } - - if (wx || wy) { - if (wx) px = wx; - if (wy) py = wy; - GetCanvasImp()->Warp(px, py); - } - - pxold = px; - pyold = py; - - if ((!fResizing && opaque) || (fResizing && ropaque)) { - if (px != pxorg || py != pyorg) { - if (pA) - action(kFALSE, pxold, pyt, pxt, pyold); - if (pB) - action(kFALSE, pxl, pyt, pxold, pyold); - if (pC) - action(kFALSE, pxl, pyold, pxold, pyl); - if (pD) - action(kFALSE, pxold, pyold, pxt, pyl); - if (pTop || pBot || pL || pR || pINSIDE) - action(kFALSE, px1, py1, px2, py2); + paint_or_set(!ropaque); + break; + case pD: + if (!ropaque) paint_or_set(kTRUE); + px1 = TMath::Max(px1p, TMath::Min(px, px2 - kMinSize)); + py1 = TMath::Min(py1p, TMath::Max(py, py2 + kMinSize)); + if (!adjustRatio(1)) { + px1 = prevpx1; + py1 = prevpy1; } + paint_or_set(!ropaque); + break; + case pTop: + if (!ropaque) paint_or_set(kTRUE); + py2 = TMath::Max(py2p, TMath::Min(py, py1 - kMinSize)); + if (!adjustRatio(11)) + py2 = prevpy2; + paint_or_set(!ropaque); + break; + case pBot: + if (!ropaque) paint_or_set(kTRUE); + py1 = TMath::Min(py1p, TMath::Max(py, py2 + kMinSize)); + if (!adjustRatio(11)) + py1 = prevpy1; + paint_or_set(!ropaque); + break; + case pL: + if (!ropaque) paint_or_set(kTRUE); + px1 = TMath::Max(px1p, TMath::Min(px, px2 - kMinSize)); + if (!adjustRatio(0)) + px1 = prevpx1; + paint_or_set(!ropaque); + break; + case pR: + if (!ropaque) paint_or_set(kTRUE); + px2 = TMath::Min(px2p, TMath::Max(px, px1 + kMinSize)); + if (!adjustRatio(0)) + px2 = prevpx2; + paint_or_set(!ropaque); + break; + case pINSIDE: + if (!opaque) paint_or_set(kTRUE); // draw the old box + px2 += px - dpx1 - px1; + px1 = px - dpx1; + py1 += py - dpy2 - py2; + py2 = py - dpy2; + if (px1 < px1p) { px2 += px1p - px1; px1 = px1p; } + if (px2 > px2p) { px1 -= px2 - px2p; px2 = px2p; } + if (py1 > py1p) { py2 -= py1 - py1p; py1 = py1p; } + if (py2 < py2p) { py1 += py2p - py2; py2 = py2p; } + paint_or_set(!opaque); // draw the new box + break; + } + if ((mode == pINSIDE && opaque) || (fResizing && ropaque)) { // Reset pad parameters and recompute conversion coefficients ResizePad(); - - if (pINSIDE) gPad->ShowGuidelines(this, event); - if (pTop) gPad->ShowGuidelines(this, event, 't', true); - if (pBot) gPad->ShowGuidelines(this, event, 'b', true); - if (pL) gPad->ShowGuidelines(this, event, 'l', true); - if (pR) gPad->ShowGuidelines(this, event, 'r', true); - if (pA) gPad->ShowGuidelines(this, event, '1', true); - if (pB) gPad->ShowGuidelines(this, event, '2', true); - if (pC) gPad->ShowGuidelines(this, event, '3', true); - if (pD) gPad->ShowGuidelines(this, event, '4', true); + switch(mode) { + case pINSIDE: gPad->ShowGuidelines(this, event); break; + case pTop: gPad->ShowGuidelines(this, event, 't', true); break; + case pBot: gPad->ShowGuidelines(this, event, 'b', true); break; + case pL: gPad->ShowGuidelines(this, event, 'l', true); break; + case pR: gPad->ShowGuidelines(this, event, 'r', true); break; + case pA: gPad->ShowGuidelines(this, event, '1', true); break; + case pB: gPad->ShowGuidelines(this, event, '2', true); break; + case pC: gPad->ShowGuidelines(this, event, '3', true); break; + case pD: gPad->ShowGuidelines(this, event, '4', true); break; + default: break; + } Modified(kTRUE); } @@ -2387,29 +2281,21 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) case kButton1Up: + if (opaque || ropaque) + ShowGuidelines(this, event); + if (gROOT->IsEscaped()) { gROOT->SetEscape(kFALSE); + fResizing = kFALSE; + mode = pNone; break; } - if (opaque||ropaque) { - ShowGuidelines(this, event); - } else { - if (pA) - action(kFALSE, pxold, pyt, pxt, pyold); - if (pB) - action(kFALSE, pxl, pyt, pxold, pyold); - if (pC) - action(kFALSE, pxl, pyold, pxold, pyl); - if (pD) - action(kFALSE, pxold, pyold, pxt, pyl); - if (pTop || pBot || pL || pR || pINSIDE) - action(kFALSE, px1, py1, px2, py2); - - if (pA || pB || pC || pD || pTop || pL || pR || pBot) - Modified(kTRUE); + if ((mode == pINSIDE && !opaque) || (fResizing && !ropaque)) { + paint_or_set(kFALSE); - pp->SetAttLine({-1, 1, -1}); + if (fResizing) + Modified(kTRUE); // Reset pad parameters and recompute conversion coefficients ResizePad(); @@ -2418,6 +2304,9 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) RangeChanged(); } + mode = pNone; + fResizing = kFALSE; + break; case kButton1Locate: diff --git a/graf2d/gpad/src/TPadPainter.cxx b/graf2d/gpad/src/TPadPainter.cxx index cfb96aa2d5785..491c00c4bd315 100644 --- a/graf2d/gpad/src/TPadPainter.cxx +++ b/graf2d/gpad/src/TPadPainter.cxx @@ -70,6 +70,8 @@ Implement TVirtualPadPainter which abstracts painting operations. TPadPainter::TPadPainter() { + fDoubleBuffer = 1; + fWinContext = (WinContext_t) 0; } /* @@ -184,6 +186,18 @@ void TPadPainter::SetDrawMode(Int_t device, Int_t mode) gVirtualX->SetDrawModeW(gVirtualX->GetWindowContext(device), (TVirtualX::EDrawMode) mode); } +//////////////////////////////////////////////////////////////////////////////// +/// Set double buffer mode for specified device + +void TPadPainter::SetDoubleBuffer(Int_t device, Int_t mode) +{ + // important flag - when disabled canvas pixmap used directly + // so one need to use absolute coordinates + fDoubleBuffer = mode; + + gVirtualX->SetDoubleBuffer(device, mode); +} + //////////////////////////////////////////////////////////////////////////////// ///Noop, for non-gl pad TASImage calls gVirtualX->CopyArea. @@ -240,10 +254,10 @@ void TPadPainter::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) if (fAttLine.GetLineWidth() <= 0) return; - const Int_t px1 = gPad->XtoPixel(x1); - const Int_t px2 = gPad->XtoPixel(x2); - const Int_t py1 = gPad->YtoPixel(y1); - const Int_t py2 = gPad->YtoPixel(y2); + const Int_t px1 = fDoubleBuffer ? gPad->XtoPixel(x1) : gPad->XtoAbsPixel(x1); + const Int_t px2 = fDoubleBuffer ? gPad->XtoPixel(x2) : gPad->XtoAbsPixel(x2); + const Int_t py1 = fDoubleBuffer ? gPad->YtoPixel(y1) : gPad->YtoAbsPixel(y1); + const Int_t py2 = fDoubleBuffer ? gPad->YtoPixel(y2) : gPad->YtoAbsPixel(y2); gVirtualX->DrawLineW(fWinContext, px1, py1, px2, py2); } @@ -256,10 +270,10 @@ void TPadPainter::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2 if (fAttLine.GetLineWidth() <= 0) return; - const Int_t px1 = gPad->UtoPixel(u1); - const Int_t py1 = gPad->VtoPixel(v1); - const Int_t px2 = gPad->UtoPixel(u2); - const Int_t py2 = gPad->VtoPixel(v2); + const Int_t px1 = fDoubleBuffer ? gPad->UtoPixel(u1) : gPad->UtoAbsPixel(u1); + const Int_t py1 = fDoubleBuffer ? gPad->VtoPixel(v1) : gPad->VtoAbsPixel(v1); + const Int_t px2 = fDoubleBuffer ? gPad->UtoPixel(u2) : gPad->UtoAbsPixel(u2); + const Int_t py2 = fDoubleBuffer ? gPad->VtoPixel(v2) : gPad->VtoAbsPixel(v2); gVirtualX->DrawLineW(fWinContext, px1, py1, px2, py2); } @@ -272,10 +286,10 @@ void TPadPainter::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, EB if (fAttLine.GetLineWidth() <= 0 && mode == TVirtualPadPainter::kHollow) return; - Int_t px1 = gPad->XtoPixel(x1); - Int_t px2 = gPad->XtoPixel(x2); - Int_t py1 = gPad->YtoPixel(y1); - Int_t py2 = gPad->YtoPixel(y2); + Int_t px1 = fDoubleBuffer ? gPad->XtoPixel(x1) : gPad->XtoAbsPixel(x1); + Int_t px2 = fDoubleBuffer ? gPad->XtoPixel(x2) : gPad->XtoAbsPixel(x2); + Int_t py1 = fDoubleBuffer ? gPad->YtoPixel(y1) : gPad->YtoAbsPixel(y1); + Int_t py2 = fDoubleBuffer ? gPad->YtoPixel(y2) : gPad->YtoAbsPixel(y2); // Box width must be at least one pixel (WTF is this code???) if (TMath::Abs(px2 - px1) < 1) diff --git a/graf2d/graf/src/TArrow.cxx b/graf2d/graf/src/TArrow.cxx index b9f2ff414943f..85dd8ad19236b 100644 --- a/graf2d/graf/src/TArrow.cxx +++ b/graf2d/graf/src/TArrow.cxx @@ -116,9 +116,7 @@ void TArrow::Copy(TObject &obj) const void TArrow::Draw(Option_t *option) { - Option_t *opt; - if (option && strlen(option)) opt = option; - else opt = (char*)GetOption(); + Option_t *opt = option && *option ? option : GetOption(); AppendPad(opt); } @@ -130,15 +128,15 @@ void TArrow::Draw(Option_t *option) /// - if `option=""`, `option` will be the current arrow option TArrow *TArrow::DrawArrow(Double_t x1, Double_t y1,Double_t x2, Double_t y2, - Float_t arrowsize ,Option_t *option) + Float_t arrowsize, Option_t *option) { Float_t size = arrowsize; if (size <= 0) size = fArrowSize; if (size <= 0) size = 0.05; - const char* opt = option; - if (!opt || !opt[0]) opt = fOption.Data(); - if (!opt || !opt[0]) opt = "|>"; + Option_t* opt = option; + if (!opt || !*opt) opt = GetOption(); + if (!opt || !*opt) opt = "|>"; TArrow *newarrow = new TArrow(x1,y1,x2,y2,size,opt); newarrow->SetAngle(fAngle); TAttLine::Copy(*newarrow); @@ -154,14 +152,9 @@ TArrow *TArrow::DrawArrow(Double_t x1, Double_t y1,Double_t x2, Double_t y2, void TArrow::Paint(Option_t *option) { if (!gPad) return; - Option_t *opt; - if (option && strlen(option)) opt = option; - else opt = (char*)GetOption(); + Option_t *opt = option && *option ? option : GetOption(); if (TestBit(kLineNDC)) - PaintArrow(gPad->GetX1() + fX1 * (gPad->GetX2() - gPad->GetX1()), - gPad->GetY1() + fY1 * (gPad->GetY2() - gPad->GetY1()), - gPad->GetX1() + fX2 * (gPad->GetX2() - gPad->GetX1()), - gPad->GetY1() + fY2 * (gPad->GetY2() - gPad->GetY1()), fArrowSize, opt); + PaintArrowNDC(fX1, fY1, fX2, fY2, fArrowSize, opt); else PaintArrow(gPad->XtoPad(fX1), gPad->YtoPad(fY1), gPad->XtoPad(fX2), gPad->YtoPad(fY2), fArrowSize, opt); } @@ -173,11 +166,12 @@ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Float_t arrowsize, Option_t *option) { if (!gPad) return; + auto &parent = *gPad; // Compute the gPad coordinates in TRUE normalized space (NDC) - Int_t iw = gPad->GetWw(); - Int_t ih = gPad->GetWh(); + Int_t iw = parent.GetWw(); + Int_t ih = parent.GetWh(); Double_t x1p,y1p,x2p,y2p; - gPad->GetPadPar(x1p,y1p,x2p,y2p); + parent.GetPadPar(x1p,y1p,x2p,y2p); Int_t ix1 = (Int_t)(iw*x1p); Int_t iy1 = (Int_t)(ih*y1p); Int_t ix2 = (Int_t)(iw*x2p); @@ -187,8 +181,8 @@ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, // Option and attributes TString opt = option; opt.ToLower(); - TAttLine::Modify(); - TAttFill::Modify(); + TAttLine::ModifyOn(parent); + TAttFill::ModifyOn(parent); Double_t wndc = TMath::Min(1.,(Double_t)iw/(Double_t)ih); @@ -202,7 +196,7 @@ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, // Ratios to convert user space in TRUE normalized space (NDC) Double_t rx1,ry1,rx2,ry2; - gPad->GetRange(rx1,ry1,rx2,ry2); + parent.GetRange(rx1,ry1,rx2,ry2); Double_t rx = (x2ndc-x1ndc)/(rx2-rx1); Double_t ry = (y2ndc-y1ndc)/(ry2-ry1); @@ -274,7 +268,7 @@ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, yarr[i] = (1/ry)*(yarr[i]-y1ndc)+ry1; } // paint arrow main line with start/stop segment together - gPad->PaintSegments(cnt/2, xarr, yarr); + parent.PaintSegments(cnt/2, xarr, yarr); // Draw the arrow's head(s) if (opt.Contains(">")) { @@ -295,15 +289,15 @@ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, y2ar[i] = (1/ry)*(y2ar[i]-y1ndc)+ry1; } if (opt.Contains("|>")) { - gPad->GetPainter()->SetLineStyle(1); + parent.GetPainter()->SetLineStyle(1); if (GetFillColor()) { - gPad->PaintFillArea(3,x2ar,y2ar); - gPad->PaintPolyLine(4,x2ar,y2ar); + parent.PaintFillArea(3,x2ar,y2ar); + parent.PaintPolyLine(4,x2ar,y2ar); } else { - gPad->PaintPolyLine(4,x2ar,y2ar); + parent.PaintPolyLine(4,x2ar,y2ar); } } else { - gPad->PaintPolyLine(3,x2ar,y2ar); + parent.PaintPolyLine(3,x2ar,y2ar); } } @@ -324,15 +318,15 @@ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, y1ar[i] = (1/ry)*(y1ar[i]-y1ndc)+ry1; } if (opt.Contains("<|")) { - gPad->GetPainter()->SetLineStyle(1); + parent.GetPainter()->SetLineStyle(1); if (GetFillColor()) { - gPad->PaintFillArea(3,x1ar,y1ar); - gPad->PaintPolyLine(4,x1ar,y1ar); + parent.PaintFillArea(3,x1ar,y1ar); + parent.PaintPolyLine(4,x1ar,y1ar); } else { - gPad->PaintPolyLine(4,x1ar,y1ar); + parent.PaintPolyLine(4,x1ar,y1ar); } } else { - gPad->PaintPolyLine(3,x1ar,y1ar); + parent.PaintPolyLine(3,x1ar,y1ar); } } } diff --git a/graf2d/graf/src/TBox.cxx b/graf2d/graf/src/TBox.cxx index efbdc510afd67..06577f2eb63b6 100644 --- a/graf2d/graf/src/TBox.cxx +++ b/graf2d/graf/src/TBox.cxx @@ -231,50 +231,56 @@ TBox *TBox::DrawBox(Double_t x1, Double_t y1,Double_t x2, Double_t y2) void TBox::ExecuteEvent(Int_t event, Int_t px, Int_t py) { + if (TestBit(kCannotMove)) return; + if (!gPad) return; - if (!gPad->IsEditable() && event != kMouseEnter) return; - if (TestBit(kCannotMove)) return; + auto &parent = *gPad; + + if (!parent.IsEditable() && event != kMouseEnter) return; Bool_t isBox = !(InheritsFrom("TPave") || InheritsFrom("TWbox")); constexpr Int_t kMaxDiff = 7; constexpr Int_t kMinSize = 20; - static Int_t px1, px2, py1, py2, pxl, pyl, pxt, pyt, pxold, pyold; - static Int_t px1p, px2p, py1p, py2p, pxlp, pylp, pxtp, pytp; + static Int_t px1, px2, py1, py2, dpx1, dpy2; + static Int_t px1p, px2p, py1p, py2p; static Double_t oldX1, oldY1, oldX2, oldY2; - static Bool_t pA, pB, pC, pD, pTop, pL, pR, pBot, pINSIDE; - Int_t wx, wy; - auto parent = gPad; - Bool_t opaque = parent->OpaqueMoving(); - Bool_t ropaque = parent->OpaqueResizing(); + static Bool_t hasOld = kFALSE; + static enum { pNone, pA, pB, pC, pD, pTop, pL, pR, pBot, pINSIDE } mode = pNone; + static bool firstPaint = kFALSE; + Bool_t opaque = parent.OpaqueMoving(); + Bool_t ropaque = parent.OpaqueResizing(); // convert to user coordinates and either paint ot set back - auto action = [parent,isBox,this](Bool_t paint, Int_t _x1, Int_t _y1, Int_t _x2, Int_t _y2) { - auto x1 = parent->AbsPixeltoX(_x1); - auto y1 = parent->AbsPixeltoY(_y1); - auto x2 = parent->AbsPixeltoX(_x2); - auto y2 = parent->AbsPixeltoY(_y2); - if (isBox) { - if (parent->GetLogx()) { - x1 = TMath::Power(10, x1); - x2 = TMath::Power(10, x2); + auto paint_or_set = [&parent,isBox,this](Bool_t paint) + { + auto x1 = parent.AbsPixeltoX(px1); + auto y1 = parent.AbsPixeltoY(py1); + auto x2 = parent.AbsPixeltoX(px2); + auto y2 = parent.AbsPixeltoY(py2); + if (!paint) { + if (isBox) { + if (parent.GetLogx()) { + x1 = TMath::Power(10, x1); + x2 = TMath::Power(10, x2); + } + if (parent.GetLogy()) { + y1 = TMath::Power(10, y1); + y2 = TMath::Power(10, y2); + } } - if (parent->GetLogy()) { - y1 = TMath::Power(10, y1); - y2 = TMath::Power(10, y2); - } - } - if (paint) { - auto pp = parent->GetPainter(); - pp->SetAttLine({GetFillColor() > 0 ? GetFillColor() : (Color_t) 1, GetLineStyle(), 2}); - pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow); - } else { SetX1(x1); SetY1(y1); SetX2(x2); SetY2(y2); + } else if (firstPaint) { + firstPaint = kFALSE; + } else { + auto pp = parent.GetPainter(); + pp->SetAttLine({GetFillColor() > 0 ? GetFillColor() : (Color_t) 1, GetLineStyle(), 2}); + pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow); } }; @@ -283,11 +289,7 @@ void TBox::ExecuteEvent(Int_t event, Int_t px, Int_t py) switch (event) { case kMouseEnter: - if (fTip) parent->ResetToolTip(fTip); - break; - - case kButton1Double: - px1 = -1; //used by kButton1Up + if (fTip) parent.ResetToolTip(fTip); break; case kArrowKeyPress: @@ -297,261 +299,186 @@ void TBox::ExecuteEvent(Int_t event, Int_t px, Int_t py) oldY1 = fY1; oldX2 = fX2; oldY2 = fY2; + hasOld = kTRUE; // No break !!! case kMouseMotion: - px1 = parent->XtoAbsPixel(isBox ? parent->XtoPad(GetX1()) : GetX1()); - py1 = parent->YtoAbsPixel(isBox ? parent->YtoPad(GetY1()) : GetY1()); - px2 = parent->XtoAbsPixel(isBox ? parent->XtoPad(GetX2()) : GetX2()); - py2 = parent->YtoAbsPixel(isBox ? parent->YtoPad(GetY2()) : GetY2()); - - if (px1 < px2) { - pxl = px1; - pxt = px2; - } else { - pxl = px2; - pxt = px1; - } - if (py1 < py2) { - pyl = py1; - pyt = py2; - } else { - pyl = py2; - pyt = py1; - } - - px1p = parent->XtoAbsPixel(parent->GetX1()) + parent->GetBorderSize(); - py1p = parent->YtoAbsPixel(parent->GetY1()) - parent->GetBorderSize(); - px2p = parent->XtoAbsPixel(parent->GetX2()) - parent->GetBorderSize(); - py2p = parent->YtoAbsPixel(parent->GetY2()) + parent->GetBorderSize(); - - if (px1p < px2p) { - pxlp = px1p; - pxtp = px2p; - } else { - pxlp = px2p; - pxtp = px1p; - } - if (py1p < py2p) { - pylp = py1p; - pytp = py2p; - } else { - pylp = py2p; - pytp = py1p; - } - - pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE; - - // case pA - if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) { - pxold = pxl; pyold = pyl; pA = kTRUE; - parent->SetCursor(kTopLeft); - } - // case pB - if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) { - pxold = pxt; pyold = pyl; pB = kTRUE; - parent->SetCursor(kTopRight); - } - // case pC - if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) { - pxold = pxt; pyold = pyt; pC = kTRUE; - parent->SetCursor(kBottomRight); - } - // case pD - if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) { - pxold = pxl; pyold = pyt; pD = kTRUE; - parent->SetCursor(kBottomLeft); - } - // top edge - if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) && TMath::Abs(py - pyl) < kMaxDiff) { - pxold = pxl; pyold = pyl; pTop = kTRUE; - parent->SetCursor(kTopSide); - } - // bottom edge - if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) && TMath::Abs(py - pyt) < kMaxDiff) { - pxold = pxt; pyold = pyt; pBot = kTRUE; - parent->SetCursor(kBottomSide); - } - // left edge - if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) && TMath::Abs(px - pxl) < kMaxDiff) { - pxold = pxl; pyold = pyl; pL = kTRUE; - parent->SetCursor(kLeftSide); - } - // right edge - if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) && TMath::Abs(px - pxt) < kMaxDiff) { - pxold = pxt; pyold = pyt; pR = kTRUE; - parent->SetCursor(kRightSide); - } - // inside box - if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) && (py > pyl+kMaxDiff && py < pyt-kMaxDiff)) { - pxold = px; pyold = py; pINSIDE = kTRUE; + px1 = parent.XtoAbsPixel(isBox ? parent.XtoPad(GetX1()) : GetX1()); + py1 = parent.YtoAbsPixel(isBox ? parent.YtoPad(GetY1()) : GetY1()); + px2 = parent.XtoAbsPixel(isBox ? parent.XtoPad(GetX2()) : GetX2()); + py2 = parent.YtoAbsPixel(isBox ? parent.YtoPad(GetY2()) : GetY2()); + if (px1 > px2) + std::swap(px1, px2); + if (py1 < py2) + std::swap(py1, py2); + + px1p = parent.XtoAbsPixel(parent.GetX1()) + parent.GetBorderSize(); + py1p = parent.YtoAbsPixel(parent.GetY1()) - parent.GetBorderSize(); + px2p = parent.XtoAbsPixel(parent.GetX2()) - parent.GetBorderSize(); + py2p = parent.YtoAbsPixel(parent.GetY2()) + parent.GetBorderSize(); + if (px1p > px2p) + std::swap(px1p, px2p); + if (py1p < py2p) + std::swap(py1p, py2p); + + mode = pNone; + + if (TMath::Abs(px - px1) <= kMaxDiff && TMath::Abs(py - py2) <= kMaxDiff) { + mode = pA; + parent.SetCursor(kTopLeft); + } else if (TMath::Abs(px - px2) <= kMaxDiff && TMath::Abs(py - py2) <= kMaxDiff) { + mode = pB; + parent.SetCursor(kTopRight); + } else if (TMath::Abs(px - px2) <= kMaxDiff && TMath::Abs(py - py1) <= kMaxDiff) { + mode = pC; + parent.SetCursor(kBottomRight); + } else if (TMath::Abs(px - px1) <= kMaxDiff && TMath::Abs(py - py1) <= kMaxDiff) { + mode = pD; + parent.SetCursor(kBottomLeft); + } else if ((px > px1 + kMaxDiff && px < px2 - kMaxDiff) && TMath::Abs(py - py2) < kMaxDiff) { + mode = pTop; + parent.SetCursor(kTopSide); + } else if ((px > px1 + kMaxDiff && px < px2 - kMaxDiff) && TMath::Abs(py - py1) < kMaxDiff) { + mode = pBot; + parent.SetCursor(kBottomSide); + } else if ((py > py2 + kMaxDiff && py < py1 - kMaxDiff) && TMath::Abs(px - px1) < kMaxDiff) { + mode = pL; + parent.SetCursor(kLeftSide); + } else if ((py > py2 + kMaxDiff && py < py1 - kMaxDiff) && TMath::Abs(px - px2) < kMaxDiff) { + mode = pR; + parent.SetCursor(kRightSide); + } else if ((px > px1+kMaxDiff && px < px2-kMaxDiff) && (py > py2+kMaxDiff && py < py1-kMaxDiff)) { + dpx1 = px - px1; // cursor position relative to top-left corner + dpy2 = py - py2; + mode = pINSIDE; if (event == kButton1Down) - parent->SetCursor(kMove); + parent.SetCursor(kMove); else - parent->SetCursor(kCross); + parent.SetCursor(kCross); } - fResizing = pA || pB || pC || pD || pTop || pL || pR || pBot; - - if (!fResizing && !pINSIDE) - parent->SetCursor(kCross); + fResizing = (mode != pNone) && (mode != pINSIDE); + firstPaint = kTRUE; + if (mode == pNone) + parent.SetCursor(kCross); break; case kArrowKeyRelease: case kButton1Motion: - wx = wy = 0; - - if (pA) { - if (!ropaque) action(kTRUE, pxold, pyt, pxt, pyold); // draw the old box - if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; } - if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; } - if (px < pxlp) { px = pxlp; wx = px; } - if (py < pylp) { py = pylp; wy = py; } - if (!ropaque) action(kTRUE, px, pyt, pxt, py); // draw the new box - } - if (pB) { - if (!ropaque) action(kTRUE, pxl, pyt, pxold, pyold); - if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; } - if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; } - if (px > pxtp) { px = pxtp; wx = px; } - if (py < pylp) { py = pylp; wy = py; } - if (!ropaque) action(kTRUE, pxl, pyt, px, py); - } - if (pC) { - if (!ropaque) action(kTRUE, pxl, pyl, pxold, pyold); - if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; } - if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; } - if (px > pxtp) { px = pxtp; wx = px; } - if (py > pytp) { py = pytp; wy = py; } - if (!ropaque) action(kTRUE, pxl, pyl, px, py); - } - if (pD) { - if (!ropaque) action(kTRUE, pxold, pyold, pxt, pyl); - if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; } - if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; } - if (px < pxlp) { px = pxlp; wx = px; } - if (py > pytp) { py = pytp; wy = py; } - if (!ropaque) action(kTRUE, px, py, pxt, pyl); - } - if (pTop) { - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - py2 += py - pyold; - if (py2 > py1-kMinSize) { py2 = py1-kMinSize; wy = py2; } - if (py2 < py2p) { py2 = py2p; wy = py2; } - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - } - if (pBot) { - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - py1 += py - pyold; - if (py1 < py2+kMinSize) { py1 = py2+kMinSize; wy = py1; } - if (py1 > py1p) { py1 = py1p; wy = py1; } - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - } - if (pL) { - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - px1 += px - pxold; - if (px1 > px2-kMinSize) { px1 = px2-kMinSize; wx = px1; } - if (px1 < px1p) { px1 = px1p; wx = px1; } - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - } - if (pR) { - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - px2 += px - pxold; - if (px2 < px1+kMinSize) { px2 = px1+kMinSize; wx = px2; } - if (px2 > px2p) { px2 = px2p; wx = px2; } - if (!ropaque) action(kTRUE, px1, py1, px2, py2); - } - if (pINSIDE) { - if (!opaque) action(kTRUE, px1, py1, px2, py2); // draw the old box - Int_t dx = px - pxold; - Int_t dy = py - pyold; - px1 += dx; py1 += dy; px2 += dx; py2 += dy; - if (px1 < px1p) { dx = px1p - px1; px1 += dx; px2 += dx; wx = px+dx; } - if (px2 > px2p) { dx = px2 - px2p; px1 -= dx; px2 -= dx; wx = px-dx; } - if (py1 > py1p) { dy = py1 - py1p; py1 -= dy; py2 -= dy; wy = py-dy; } - if (py2 < py2p) { dy = py2p - py2; py1 += dy; py2 += dy; wy = py+dy; } - if (!opaque) action(kTRUE, px1, py1, px2, py2); // draw the new box - } - - if (wx || wy) { - if (wx) px = wx; - if (wy) py = wy; - parent->GetCanvasImp()->Warp(px, py); + switch (mode) { + case pNone: + return; + case pA: + if (!ropaque) paint_or_set(kTRUE); + px1 = TMath::Max(px1p, TMath::Min(px, px2 - kMinSize)); + py2 = TMath::Max(py2p, TMath::Min(py, py1 - kMinSize)); + paint_or_set(!ropaque); + break; + case pB: + if (!ropaque) paint_or_set(kTRUE); + px2 = TMath::Min(px2p, TMath::Max(px, px1 + kMinSize)); + py2 = TMath::Max(py2p, TMath::Min(py, py1 - kMinSize)); + paint_or_set(!ropaque); + break; + case pC: + if (!ropaque) paint_or_set(kTRUE); + px2 = TMath::Min(px2p, TMath::Max(px, px1 + kMinSize)); + py1 = TMath::Min(py1p, TMath::Max(py, py2 + kMinSize)); + paint_or_set(!ropaque); + break; + case pD: + if (!ropaque) paint_or_set(kTRUE); + px1 = TMath::Max(px1p, TMath::Min(px, px2 - kMinSize)); + py1 = TMath::Min(py1p, TMath::Max(py, py2 + kMinSize)); + paint_or_set(!ropaque); + break; + case pTop: + if (!ropaque) paint_or_set(kTRUE); + py2 = TMath::Max(py2p, TMath::Min(py, py1 - kMinSize)); + paint_or_set(!ropaque); + break; + case pBot: + if (!ropaque) paint_or_set(kTRUE); + py1 = TMath::Min(py1p, TMath::Max(py, py2 + kMinSize)); + paint_or_set(!ropaque); + break; + case pL: + if (!ropaque) paint_or_set(kTRUE); + px1 = TMath::Max(px1p, TMath::Min(px, px2 - kMinSize)); + paint_or_set(!ropaque); + break; + case pR: + if (!ropaque) paint_or_set(kTRUE); + px2 = TMath::Min(px2p, TMath::Max(px, px1 + kMinSize)); + paint_or_set(!ropaque); + break; + case pINSIDE: + if (!opaque) paint_or_set(kTRUE); + px2 += px - dpx1 - px1; + px1 = px - dpx1; + py1 += py - dpy2 - py2; + py2 = py - dpy2; + if (px1 < px1p) { px2 += px1p - px1; px1 = px1p; } + if (px2 > px2p) { px1 -= px2 - px2p; px2 = px2p; } + if (py1 > py1p) { py2 -= py1 - py1p; py1 = py1p; } + if (py2 < py2p) { py1 += py2p - py2; py2 = py2p; } + paint_or_set(!opaque); + break; } - pxold = px; - pyold = py; - - if ((pINSIDE && opaque) || (fResizing && ropaque)) { - if (pA) - action(kFALSE, pxold, pyt, pxt, pyold); - if (pB) - action(kFALSE, pxl, pyt, pxold, pyold); - if (pC) - action(kFALSE, pxl, pyold, pxold, pyl); - if (pD) - action(kFALSE, pxold, pyold, pxt, pyl); - if (pTop || pBot || pL || pR || pINSIDE) - action(kFALSE, px1, py1, px2, py2); - - if (pINSIDE) parent->ShowGuidelines(this, event, 'i', true); - if (pTop) parent->ShowGuidelines(this, event, 't', true); - if (pBot) parent->ShowGuidelines(this, event, 'b', true); - if (pL) parent->ShowGuidelines(this, event, 'l', true); - if (pR) parent->ShowGuidelines(this, event, 'r', true); - if (pA) parent->ShowGuidelines(this, event, '1', true); - if (pB) parent->ShowGuidelines(this, event, '2', true); - if (pC) parent->ShowGuidelines(this, event, '3', true); - if (pD) parent->ShowGuidelines(this, event, '4', true); - parent->Modified(kTRUE); + if ((mode == pINSIDE && opaque) || (fResizing && ropaque)) { + switch(mode) { + case pINSIDE: parent.ShowGuidelines(this, event, 'i', true); break; + case pTop: parent.ShowGuidelines(this, event, 't', true); break; + case pBot: parent.ShowGuidelines(this, event, 'b', true); break; + case pL: parent.ShowGuidelines(this, event, 'l', true); break; + case pR: parent.ShowGuidelines(this, event, 'r', true); break; + case pA: parent.ShowGuidelines(this, event, '1', true); break; + case pB: parent.ShowGuidelines(this, event, '2', true); break; + case pC: parent.ShowGuidelines(this, event, '3', true); break; + case pD: parent.ShowGuidelines(this, event, '4', true); break; + default: break; // not involved + } + parent.Modified(kTRUE); } break; case kButton1Up: + if (opaque || ropaque) + parent.ShowGuidelines(this, event); + if (gROOT->IsEscaped()) { gROOT->SetEscape(kFALSE); - if (opaque || ropaque) - parent->ShowGuidelines(this, event); - if (opaque) { - SetX1(oldX1); - SetY1(oldY1); - SetX2(oldX2); - SetY2(oldY2); - parent->Modified(kTRUE); - parent->Update(); + if (opaque && (mode != pNone)) { + if (hasOld) { + SetX1(oldX1); + SetY1(oldY1); + SetX2(oldX2); + SetY2(oldY2); + } + hasOld = kFALSE; + mode = pNone; + fResizing = kFALSE; + parent.Modified(kTRUE); + parent.Update(); } break; } - if (opaque || ropaque) { - parent->ShowGuidelines(this, event); - } else { - if (px1 < 0) - break; - if (pA) - action(kFALSE, pxold, pyt, pxt, pyold); - if (pB) - action(kFALSE, pxl, pyt, pxold, pyold); - if (pC) - action(kFALSE, pxl, pyold, pxold, pyl); - if (pD) - action(kFALSE, pxold, pyold, pxt, pyl); - if (pTop || pBot || pL || pR || pINSIDE) - action(kFALSE, px1, py1, px2, py2); - if (pINSIDE) { - // if it was not a pad that was moved then it must have been - // a box or something like that so we have to redraw the pad - if (parent == gPad) parent->Modified(kTRUE); - } - } + if ((!opaque && mode == pINSIDE) || (!ropaque && fResizing)) + paint_or_set(kFALSE); + + if (mode != pNone) + parent.Modified(kTRUE); - if (pA || pB || pC || pD || pTop || pL || pR || pBot) - parent->Modified(kTRUE); + mode = pNone; + fResizing = kFALSE; + hasOld = kFALSE; break; @@ -562,7 +489,7 @@ void TBox::ExecuteEvent(Int_t event, Int_t px, Int_t py) while (true) { px = py = 0; - event = parent->GetCanvasImp()->RequestLocator(px, py); + event = parent.GetCanvasImp()->RequestLocator(px, py); ExecuteEvent(kButton1Motion, px, py); diff --git a/graf2d/graf/src/TLine.cxx b/graf2d/graf/src/TLine.cxx index fe21673a650da..8c1e791b25ede 100644 --- a/graf2d/graf/src/TLine.cxx +++ b/graf2d/graf/src/TLine.cxx @@ -145,7 +145,9 @@ void TLine::ExecuteEvent(Int_t event, Int_t px, Int_t py) auto action = [this, parent](Int_t code, Int_t _x1, Int_t _y1, Int_t _x2 = 0, Int_t _y2 = 0) { Double_t x1, y1, x2, y2; - if (TestBit(kLineNDC)) { + Bool_t isndc = TestBit(kLineNDC); + + if (isndc) { x1 = (1. * _x1 / parent->GetWw() - parent->GetAbsXlowNDC()) / parent->GetAbsWNDC(); y1 = ((1 - 1. * _y1 / parent->GetWh()) - parent->GetAbsYlowNDC()) / parent->GetAbsHNDC(); x2 = (1. * _x2 / parent->GetWw() - parent->GetAbsXlowNDC()) / parent->GetAbsWNDC(); @@ -155,23 +157,24 @@ void TLine::ExecuteEvent(Int_t event, Int_t px, Int_t py) y1 = parent->AbsPixeltoY(_y1); x2 = parent->AbsPixeltoX(_x2); y2 = parent->AbsPixeltoY(_y2); - if (parent->GetLogx()) { - x1 = TMath::Power(10, x1); - x2 = TMath::Power(10, x2); - } - if (parent->GetLogy()) { - y1 = TMath::Power(10, y1); - y2 = TMath::Power(10, y2); - } } if (code == 0) { auto pp = parent->GetPainter(); pp->SetAttLine(*this); - if (TestBit(kLineNDC)) + if (isndc) pp->DrawLineNDC(x1, y1, x2, y2); else pp->DrawLine(x1, y1, x2, y2); } else { + if (!isndc && parent->GetLogx()) { + x1 = TMath::Power(10, x1); + x2 = TMath::Power(10, x2); + } + if (!isndc && parent->GetLogy()) { + y1 = TMath::Power(10, y1); + y2 = TMath::Power(10, y2); + } + if (code & 1) { SetX1(x1); SetY1(y1); diff --git a/graf3d/gl/src/TGLPadPainter.cxx b/graf3d/gl/src/TGLPadPainter.cxx index 2236829a9eef8..3c55cef6354e1 100644 --- a/graf3d/gl/src/TGLPadPainter.cxx +++ b/graf3d/gl/src/TGLPadPainter.cxx @@ -397,12 +397,10 @@ void TGLPadPainter::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t if (fLocked) { // this code used when crosshair cursor is drawn if (fWinContext && (gVirtualX->GetDrawModeW(fWinContext) == TVirtualX::kInvert)) { - const Int_t px1 = gPad->UtoPixel(u1); - const Int_t py1 = gPad->VtoPixel(v1); - const Int_t px2 = gPad->UtoPixel(u2); - const Int_t py2 = gPad->VtoPixel(v2); // TODO: only here set line attributes to virtual x - gVirtualX->DrawLineW(fWinContext, px1, py1, px2, py2); + gVirtualX->DrawLineW(fWinContext, + gPad->UtoAbsPixel(u1), gPad->VtoAbsPixel(v1), + gPad->UtoAbsPixel(u2), gPad->VtoAbsPixel(v2)); } return; } @@ -422,7 +420,21 @@ void TGLPadPainter::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t void TGLPadPainter::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, EBoxMode mode) { - if (fLocked) return; + if (fLocked) { + //GL pad painter can be called in non-standard situation: + //not from TPad::Paint, but + //from TView3D::ExecuteRotateView. This means in fact, + //that TView3D wants to draw itself in a XOR mode, via + //gVirtualX. + // TODO: only here set line attributes to virtual x + if (fWinContext && (gVirtualX->GetDrawModeW(fWinContext) == TVirtualX::kInvert)) { + gVirtualX->DrawBoxW(fWinContext, + gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1), + gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2), + (TVirtualX::EBoxMode) mode); + } + return; + } if (IsGradientFill(GetAttFill().GetFillColor())) { Double_t xs[] = {x1, x2, x2, x1}; diff --git a/gui/gui/src/TRootCanvas.cxx b/gui/gui/src/TRootCanvas.cxx index db1bcf4b7ae84..140d47fed4010 100644 --- a/gui/gui/src/TRootCanvas.cxx +++ b/gui/gui/src/TRootCanvas.cxx @@ -263,8 +263,9 @@ TRootContainer::TRootContainer(TRootCanvas *c, Window_t id, const TGWindow *p) kButtonPressMask | kButtonReleaseMask | kPointerMotionMask, kNone, kNone); - AddInput(kKeyPressMask | kKeyReleaseMask | kPointerMotionMask | - kExposureMask | kStructureNotifyMask | kLeaveWindowMask); + AddInput(kKeyPressMask | kKeyReleaseMask | kPointerMotionMask | kExposureMask | + kStructureNotifyMask | kEnterWindowMask | kLeaveWindowMask); + fEditDisabled = kEditDisable; } @@ -1968,6 +1969,9 @@ Bool_t TRootCanvas::HandleContainerCrossing(Event_t *event) if (event->fType == kLeaveNotify && event->fCode == kNotifyNormal) fCanvas->HandleInput(kMouseLeave, x, y); + if (event->fType == kEnterNotify && event->fCode == kNotifyNormal) + fCanvas->HandleInput(kMouseEnter, x, y); + return kTRUE; } diff --git a/gui/gui/src/TRootEmbeddedCanvas.cxx b/gui/gui/src/TRootEmbeddedCanvas.cxx index 4466c68a64cd9..bcd9588bbd862 100644 --- a/gui/gui/src/TRootEmbeddedCanvas.cxx +++ b/gui/gui/src/TRootEmbeddedCanvas.cxx @@ -84,7 +84,7 @@ TRootEmbeddedContainer::TRootEmbeddedContainer(TRootEmbeddedCanvas *c, Window_t kPointerMotionMask, kNone, kNone); AddInput(kKeyPressMask | kKeyReleaseMask | kPointerMotionMask | - kExposureMask | kStructureNotifyMask | kLeaveWindowMask); + kExposureMask | kStructureNotifyMask | kEnterWindowMask | kLeaveWindowMask); fEditDisabled = kEditDisableGrab; } @@ -419,6 +419,9 @@ Bool_t TRootEmbeddedCanvas::HandleContainerCrossing(Event_t *event) if (event->fType == kLeaveNotify && event->fCode == kNotifyNormal) fCanvas->HandleInput(kMouseLeave, x, y); + if (event->fType == kEnterNotify && event->fCode == kNotifyNormal) + fCanvas->HandleInput(kMouseEnter, x, y); + return kTRUE; }