Not getting mouse events

I have some code adapted from the jucer, and I’ve ‘lost’ my mouse clicks. I have:

a tabbed holder, which contains a viewport,
which contains a magnifier, which owns a ‘workspace’, and that has a component that has sub-components I want to click.

Before I added the ‘workspace’ object I did get clicks, and now I don’t. The workspace is set up to not intercept, I think. Sound familiar?

[code]LayoutEditor::LayoutEditor (EncoreVC_Document* document_)
: document (document_),
layout(document_),
firstResize (true)
{
addAndMakeVisible (viewport = new ZoomingViewport (this)); // deals with setting the zoom
workspace = new WorkspaceComponent(3840, 2160);

jassert(workspace != NULL);

viewport->setViewedComponent (magnifier = new MagnifierComponent (workspace, true)); // contains/draws

// subCompHolder is 'in' the workspace, an arbitrary but zoomable space
workspace->addAndMakeVisible (subCompHolder = new SubComponentHolderComp (document, grid));

subCompHolder->setBounds((workspace->getWidth() - 1920) / 2, (workspace->getHeight() - 1080) / 2, 1920, 1080);

// Listen to our layout
layout.getSelectedLayers().addChangeListener (this);

setWantsKeyboardFocus (true);
setZoom (0.4f, subCompHolder->getX(), subCompHolder->getY());

[/code]

and

[code]//==============================================================================
class WorkspaceComponent : public Component
{
public:
WorkspaceComponent (double width, double height)
{
setInterceptsMouseClicks (false, false);
setWantsKeyboardFocus (false);
setBounds(0, 0, width, height);
}

~WorkspaceComponent()
{
}

void paint (Graphics& g)
{
    g.fillCheckerBoard (0, 0, getWidth(), getHeight(),
                        100, 100,
                        Colour (0xffe0e0e0),
                        Colours::white);
}

void resized()
{
}

[/code]

Thanks,

Bruce

Sorry, disregard. Found what the two bools in intercept do.

Bruce :oops:

Is the workspace comp actually visible?

Yes, but I was telling it not to get clicks for children. My bad.

I worked it out - just not when I wanted to.

Magnifier stuff is neat. I was dreading adding that and it was fine.

Bruce

The magnifier stuff works ok, but it uses quite a few cunning hacks, so don’t be surprised if you find it has a few idiosyncrasies!

Would any of those idiosyncracies make repaint artifacts? When zoomed, I get a 1 pixel light green line to the right of components when I mouse over them. At 1.0 scale, all good. I’ve scoured my drawing path and get no joy.

If I scroll the viewport (that’s being magnified) then it all cleans up.

It also happens on Mac and Window, as far as I can tell (no win here right now), at least something very similar was.

And here’s the biggest clue, it seems - as scale changes, the error doesn’t - it’s around 1 pixel. Certain scale factors only show either bottom or right lines, and there are rare factors that will show 2 pix.

This pic shows the same component after mouse-overs. Repaint drawing is on, hence the colors. The only difference is zoom factor.

Thanks, Bruce

Yeah, I can believe that it could do something like that. It was surprisingly hard to do that maths correctly for rescaling the repaint areas, but it seems ok in the jucer. Any idea what you’re doing that’s more taxing that the jucer’s UI?

That’s the odd thing. I have some extra layers between magnifier and components, I’m using different scale factors, probably - I’m doing up and down by .1, but from a ‘fit to window’ start that may be arbitrary and odd. Hmm, if I go scale 1.0 then work from there it’s the same.

I did try finding areas to go +1 - there’s a repaint section where you already have a ++ correction, but when scaled > 1.0. I tried adding a few to that, in +/1 situations - no dice.

I create the views with:

[code] setWantsKeyboardFocus (true);
addAndMakeVisible (viewport = new ZoomingViewport (this)); // deals with setting the zoom
workspace = new WorkspaceComponent(defaultHRes * 3, defaultVRes * 3);

jassert(workspace != NULL);

viewport->setViewedComponent (magnifier = new MagnifierComponent (workspace, true)); // contains/draws

// subCompHolder is 'in' the workspace, an arbitrary but zoomable space
workspace->addAndMakeVisible (subCompHolder = new SubComponentHolderComp (document, grid));

subCompHolder->setBounds(defaultHRes, defaultVRes, defaultHRes, defaultVRes);

[/code] Then add sub components to the subcompholder, and overlays to the workspace. workspace->addAndMakeVisible (overlay);
I know if the sub-compholder doesn’t draw it’s the same. If the deep components don’t draw it’s the same… If the overlays don’t draw, and don’t make a resizeable border, it’s the same. I also tried to move the overlays to the subcompholder - no dice there.

So it seems to be repaint related - I tried to make pic background in case it’s a stored image being stuck wrong, nope. I wonder why it’s green??

I don’t know if anything occurred to you Jules, but I moved my lasso into my workspace component, and that’s quite flamboyant too. It seems that any components in my ‘workspace’ (it’s own paint seems OK) draw with green artifacts.

The workspace is contained by the magnifier, which is contained by the viewport.

Another component is in the workspace, a bastardization of your subcompholder, and it’s children have less problems.

There must be something different in Jucer, but I haven’t spotted it yet. But finally - a clue. I looked for this before, but now I’m using a text bgnd, not checkerboard it sticks out - the problem seems to be a cut/paste of the background, presumably as something redraws, where it gets shifted. The green must be bad memory, or something. Does that help?

The green will just be uninitialised bits of the buffered image that haven’t been drawn on. All I can think of is that maybe you’re using components with negative co-ordinates and that could be causing rounding errors that don’t appear in the jucer?..

Could be, in so much as I have components inside a component in the magnifier content component. In Jucer, as I recall, all components are in the same holder.

Nothing is specifically negative, per se. Workspace is 0,0 in viewport, subcompholder is 1400,1050 or so in the workspace. When I make a lasso it’s in the workspace, it is also positive. But yes - if you drag things around, they could be negative in respect to others.

Do you have time to dig out where the rounding error is? I need to work it out for an NAB demo version :frowning:

I can’t make Jucer do it, I could try to make a demo file, or email you the actual problem exposing code.

Bruce

Well the error’s almost certainly going to be in MagnifyingPeer::repaint(). Try adding 1 to the width and height it uses…

I’ll try that, but did you see the shift in that last image? Look at the ‘u’. It’s being re-pasted in the wrong place, as opposed to too small.

Bruce

Ah yes, I didn’t notice that. Well in that case the error must be in MagnifierComponent::paint()…

It seems to be…

I can see the rect at the start as - in one pass, 827, gets scaled to 2251, then back as 826 - so that’s obvious. Is there a reason the start co-ordinates ® do not get used for the paste back of the temp image?

I tried the simple fix:

g.drawImage (&temp, roundDoubleToInt (srcX * scaleFactor), roundDoubleToInt (srcY * scaleFactor), roundDoubleToInt ((srcR - srcX) * scaleFactor), roundDoubleToInt ((srcB - srcY) * scaleFactor),
It’s a big improvement - no greenies. But there are some minor trails still, and I suspect there’ll be edge cases where this won’t help. It seems like this section needs a rounding policy that will guarantee gerzintas will equal gerzoutas.

But thanks for the pointers and patience! I can breath again.

Bruce

OK, so still not perfect. By extending the area to be repainted,[code] void repaint (int x, int y, int w, int h)

{

    const double zoom = magnifierComp->getScaleFactor();



    magnifierComp->repaint ((int) (x * zoom) - 1,

                            (int) (y * zoom) - 1,

                            roundDoubleToInt (w * zoom) + 2,

                            roundDoubleToInt (h * zoom) + 2);

[/code] and working a bit with the image cut/paste rounding (I’ve tried a few variations)[code]void MagnifierComponent::paint (Graphics& g)

{

const Rectangle r (g.getClipBounds());



const int srcX = (int)  (r.getX() / scaleFactor);

const int srcY = (int)  (r.getY() / scaleFactor);

int srcR = roundDoubleToInt  (r.getRight() / scaleFactor);

int srcB = roundDoubleToInt  (r.getBottom() / scaleFactor);


if (scaleFactor >= 1.0)

{

    ++srcR;

    ++srcB;

}

	

Image temp (Image::ARGB, srcR - srcX, srcB - srcY, true);



Graphics g2 (temp);

g2.setOrigin (-srcX, -srcY);



holderComp->paintEntireComponent (g2);



g.setImageResamplingQuality (Graphics::lowResamplingQuality);



g.drawImage (&temp,

             r.getX(),

             r.getY(),

             r.getWidth(),

             r.getHeight(),

             0, 0,

             srcR - srcX,

             srcB - srcY,

             false);

}

[/code] I can get it quite clean, but I still get a ‘shimmy’ as I drag a lasso around. Could you suggest the ‘correct’ code please?

Bruce

It just isn’t going to work correctly at scale factors that aren’t a whole number, because if it’s drawing non-interpolated rescaled images of different subsections, then the way they’ll have their pixels distributed will vary depending on their size and position within the graphics context. I’d suggest sticking simple factors of 0.5, 2, 3, etc.

Actually, that’s wrong. It is possible, but a bit wasteful of memory. Try this:

[code]void MagnifierComponent::paint (Graphics& g)
{
const int w = holderComp->getWidth();
const int h = holderComp->getHeight();

if (w == 0 || h == 0)
    return;

const Rectangle r (g.getClipBounds());

const int srcX = (int) (r.getX() / scaleFactor);
const int srcY = (int) (r.getY() / scaleFactor);
int srcR = (int) (r.getRight() / scaleFactor);
int srcB = (int) (r.getBottom() / scaleFactor);

if (scaleFactor >= 1.0)
{
    ++srcR;
    ++srcB;
}

Image temp (Image::ARGB, w, h, true);

Graphics g2 (temp);
g2.reduceClipRegion (srcX, srcY, srcR - srcX, srcB - srcY);

holderComp->paintEntireComponent (g2);

g.setImageResamplingQuality (Graphics::lowResamplingQuality);

g.drawImage (&temp,
             0, 0, 
             (int) (w * scaleFactor),
             (int) (h * scaleFactor),
             0, 0, w, h,
             false);

}
[/code]

It looks like scrcR and B do need to be rounded after all. At some weird zoom settings you could get the yellow lines back. Haven’t seen it since I changed to roundDoubleToInt.

Bruce