bool
EDFBGraphicsWindow::HandleMouseEvent(DFBWindowEvent *event)
{
	if(dfbWindow == NULL || fHidden) return false;
	if(!(event->type == DWET_BUTTONDOWN || event->type == DWET_BUTTONUP || event->type == DWET_MOTION)) return false;

	int winLeft, winTop;
	int winWidth, winHeight;
	dfbWindow->GetPosition(dfbWindow, &winLeft, &winTop);
	dfbWindow->GetSize(dfbWindow, &winWidth, &winHeight);

	EPoint where((float)(event->cx - winLeft), (float)(event->cy - winTop));
	ERect allBounds(0, 0, (float)fWidth - 1, (float)fHeight - 1);
	ERect winBounds = allBounds;
	winBounds.left += fMargins.left;
	winBounds.top += fMargins.top;
	winBounds.right -= fMargins.right;
	winBounds.bottom -= fMargins.bottom;

	eint32 button = 0;
	if(event->type != DWET_MOTION)
	{
		if(event->button == DIBI_LEFT) button = 1;
		else if(event->button == DIBI_MIDDLE) button = 2;
		else if(event->button == DIBI_RIGHT) button = 3;
	}
	else
	{
		DFBInputDeviceButtonMask state = event->buttons;
		if(state & DIBM_LEFT) button += 1;
		if(state & DIBM_MIDDLE) button += 2;
		if(state & DIBM_RIGHT) button += 3;
	}

	if(button == 0 && !(fHandlingMove || fHandlingResize))
		return((allBounds.Contains(where) && !winBounds.Contains(where)) ? true : false);

	switch(fLook)
	{
		case E_MODAL_WINDOW_LOOK:
		case E_FLOATING_WINDOW_LOOK:
		case E_TITLED_WINDOW_LOOK:
		case E_DOCUMENT_WINDOW_LOOK:
			{
				if(fEngine->dfbCurPointerGrabbed != E_MAXUINT) break;
				if(!(allBounds.Contains(where) && !winBounds.Contains(where))) break;

				int titlebar_height = (fLook == E_FLOATING_WINDOW_LOOK ?
							DFB_WINDOW_SMALL_TITLEBAR_HEIGHT : DFB_WINDOW_NORMAL_TITLEBAR_HEIGHT);

				int btn_h = titlebar_height - 5;
				int button_space = 3;
				int btn_w = btn_h;
				int btn_x = fWidth - 1 - 4 - btn_w;
				int btn_y = 3;

				// close button
				if(!(fFlags & E_NOT_CLOSABLE) && fLook != E_MODAL_WINDOW_LOOK)
				{
					ERect buttonBounds((float)btn_x, (float)btn_y, (float)(btn_x + btn_w), (float)(btn_y + btn_h));
					if(buttonBounds.Contains(where))
					{
						if(button == 1 && event->type == DWET_BUTTONDOWN)
						{
							fMsgr.SendMessage(E_QUIT_REQUESTED);
							return true;
						}
					}
					btn_x -= btn_w + button_space;
				}

				if(button == 1 && event->type == DWET_BUTTONDOWN)
				{
					if(dfbWindow->GrabPointer(dfbWindow) != DFB_OK) break;
					fEngine->dfbCurPointerGrabbed = dfbWindowID;
					wmPointerOffsetX = event->cx - winLeft;
					wmPointerOffsetY = event->cy - winTop;
					if(where.x < 10 && where.y < 10) fHandlingResize = true; else fHandlingMove = true;
					if(!(fFlags & E_AVOID_FOCUS)) dfbWindow->RaiseToTop(dfbWindow);
					return true;
				}
			}
			break;

		default:
			break;
	}

	if(fEngine->dfbCurPointerGrabbed == dfbWindowID && (fHandlingMove || fHandlingResize))
	{
		DFBEvent evt;
		while(fEngine->dfbEventBuffer->PeekEvent(fEngine->dfbEventBuffer, &evt) == DFB_OK)
		{
			if(evt.clazz != DFEC_WINDOW) break;
			if(evt.window.window_id != dfbWindowID) break;
			if(!(evt.window.type == DWET_MOTION ||
			     evt.window.type == DWET_GOTFOCUS ||
			     evt.window.type == DWET_LOSTFOCUS)) break;
			if(fEngine->dfbEventBuffer->GetEvent(fEngine->dfbEventBuffer, &evt) != DFB_OK) break;
			if(evt.window.type == DWET_MOTION)
			{
				event->cx = evt.window.cx;
				event->cy = evt.window.cy;
			}
		}

		if(event->type == DWET_BUTTONUP)
		{
			dfbWindow->UngrabPointer(dfbWindow);
			fEngine->dfbCurPointerGrabbed = E_MAXUINT;
			fHandlingMove = false;
			fHandlingResize = false;
		}
		else if(event->type == DWET_MOTION &&
			(wmPointerOffsetX != event->cx - winLeft || wmPointerOffsetY != event->cy - winTop))
		{
			int dx = event->cx - winLeft - wmPointerOffsetX;
			int dy = event->cy - winTop - wmPointerOffsetY;

			if(fHandlingMove || fHandlingResize)
				dfbWindow->MoveTo(dfbWindow, winLeft + dx, winTop + dy);

			if(fHandlingResize)
			{
				int newWidth = max_c(winWidth - dx, (int)fMargins.left + (int)fMargins.right);
				int newHeight = max_c(winHeight - dy, (int)fMargins.top + (int)fMargins.bottom);
				if(newWidth != winWidth || newHeight != winHeight) dfbWindow->Resize(dfbWindow, newWidth, newHeight);
			}
		}

		return true;
	}

	return(fEngine->dfbCurPointerGrabbed == dfbWindowID ? false : !winBounds.Contains(where));
}
void MIDIRelayComponent::resized()
{
    int hspacing = 10;
    int vspacing = 6;
    
    // target   <________________________> | Del |
    // channel  ____  group <____________> |     |
    
    int targetLabelWidth = 60;
    int channelLabelWidth = 60;
    int channelSelectorWidth = 60;
    int groupLabelWidth = 60;
    int buttonWidth = 60;
    int rowHeight = 20;
    
    Rectangle<int> bounds = getBounds();
    
    // double margin, for the outer and inner component cell
    //Rectangle<int> rootBounds = getBounds().reduced(hmargin*4, vmargin*4).translated(hmargin*2, vmargin*2);
    
    int hackyOffset = 10;
    Rectangle<int> rootBounds = getBounds().reduced(hmargin*2, vmargin*2).translated(hmargin - hackyOffset, vmargin);
    int fullWidth = rootBounds.getWidth();
    
    // ROW1
    
    int horizontalOffset = rootBounds.getX();
    int verticalOffset = rootBounds.getY();
    
    Rectangle<int> targetLabelBounds(horizontalOffset, verticalOffset, targetLabelWidth, rowHeight);
    horizontalOffset = targetLabelBounds.getRight() + hspacing;
    targetLabel.setBounds(targetLabelBounds);
    
    int targetSelectorWidth = fullWidth - targetLabelWidth - buttonWidth - (hspacing*2);
    Rectangle<int> targetSelectorBounds(horizontalOffset, verticalOffset, targetSelectorWidth, rowHeight);
    horizontalOffset = targetSelectorBounds.getRight() + hspacing;
    targetSelectionComponent.setBounds(targetSelectorBounds);
    
    // ROW2
    
    horizontalOffset = rootBounds.getX();
    verticalOffset = rootBounds.getY() + vspacing + rowHeight;
    
    Rectangle<int> channelLabelBounds(horizontalOffset, verticalOffset, channelLabelWidth, rowHeight);
    horizontalOffset = channelLabelBounds.getRight() + hspacing;
    channelLabel.setBounds(channelLabelBounds);
    
    Rectangle<int> channelSelectorBounds(horizontalOffset, verticalOffset, channelSelectorWidth, rowHeight);
    horizontalOffset = channelSelectorBounds.getRight() + hspacing;
    channelSelectionComponent.setBounds(channelSelectorBounds);
    
    Rectangle<int> groupLabelBounds(horizontalOffset, verticalOffset, groupLabelWidth, rowHeight);
    horizontalOffset = groupLabelBounds.getRight() + hspacing;
    groupLabel.setBounds(groupLabelBounds);
    
    int groupFieldWidth = fullWidth - channelLabelWidth - channelSelectorWidth - groupLabelWidth - buttonWidth - (hspacing*4);
    Rectangle<int> groupFieldBounds(horizontalOffset, verticalOffset, groupFieldWidth, rowHeight);
    horizontalOffset = groupFieldBounds.getRight() + hspacing;
    groupField.setBounds(groupFieldBounds);
    
    // BUTTON
    
    horizontalOffset = rootBounds.getX() + fullWidth - buttonWidth;
    verticalOffset = rootBounds.getY();
    
    //int buttonHeight = (rowHeight * 2) + vspacing; // spans two rows
    Rectangle<int> buttonBounds(horizontalOffset, verticalOffset, buttonWidth, rowHeight);
    deleteButton.setBounds(buttonBounds);

}
void ParameterRelayComponent::resized()
{
    int hspacing = 10;
    int vspacing = 6;
    
    // target   <__________________> parameter ______ | Del |
    // group <____________> descriptor <____________> |     |
    
    int targetLabelWidth = 60;
    int parameterLabelWidth = 80;
    int groupLabelWidth = 60;
    int descriptorLabelWidth = 80;
    int buttonWidth = 60;
    int rowHeight = 20;
    
    Rectangle<int> bounds = getBounds();
    
    // double margin, for the outer and inner component cell
    //Rectangle<int> rootBounds = getBounds().reduced(hmargin*4, vmargin*4).translated(hmargin*2, vmargin*2);
    
    int hackyOffset = 10;
    Rectangle<int> rootBounds = getBounds().reduced(hmargin*2, vmargin*2).translated(hmargin - hackyOffset, vmargin);
    int fullWidth = rootBounds.getWidth();
    
    // ROW1
    
    int horizontalOffset = rootBounds.getX();
    int verticalOffset = rootBounds.getY();
    
    int flexWidth = (fullWidth - targetLabelWidth - parameterLabelWidth - buttonWidth - (hspacing*4)) / 2;
    
    Rectangle<int> targetLabelBounds(horizontalOffset, verticalOffset, targetLabelWidth, rowHeight);
    horizontalOffset = targetLabelBounds.getRight() + hspacing;
    targetLabel.setBounds(targetLabelBounds);
    
    Rectangle<int> targetSelectorBounds(horizontalOffset, verticalOffset, flexWidth, rowHeight);
    horizontalOffset = targetSelectorBounds.getRight() + hspacing;
    targetSelectionComponent.setBounds(targetSelectorBounds);
    
    Rectangle<int> parameterLabelBounds(horizontalOffset, verticalOffset, parameterLabelWidth, rowHeight);
    horizontalOffset = parameterLabelBounds.getRight() + hspacing;
    parameterLabel.setBounds(parameterLabelBounds);
    
    Rectangle<int> parameterSelectionBounds(horizontalOffset, verticalOffset, flexWidth, rowHeight);
    horizontalOffset = parameterSelectionBounds.getRight() + hspacing;
    parameterSelectionComponent.setBounds(parameterSelectionBounds);
    
    // ROW2
    
    horizontalOffset = rootBounds.getX();
    verticalOffset = rootBounds.getY() + vspacing + rowHeight;
    
    flexWidth = (fullWidth - groupLabelWidth - descriptorLabelWidth - buttonWidth - (hspacing*4)) / 2;
    
    Rectangle<int> groupLabelBounds(horizontalOffset, verticalOffset, groupLabelWidth, rowHeight);
    horizontalOffset = groupLabelBounds.getRight() + hspacing;
    groupLabel.setBounds(groupLabelBounds);
    
    Rectangle<int> groupFieldBounds(horizontalOffset, verticalOffset, flexWidth, rowHeight);
    horizontalOffset = groupFieldBounds.getRight() + hspacing;
    groupField.setBounds(groupFieldBounds);
    
    Rectangle<int> descriptorLabelBounds(horizontalOffset, verticalOffset, descriptorLabelWidth, rowHeight);
    horizontalOffset = descriptorLabelBounds.getRight() + hspacing;
    descriptorLabel.setBounds(descriptorLabelBounds);
    
    Rectangle<int> descriptorFieldBounds(horizontalOffset, verticalOffset, flexWidth, rowHeight);
    horizontalOffset = descriptorFieldBounds.getRight() + hspacing;
    descriptorField.setBounds(descriptorFieldBounds);
    
    
    // BUTTON
    
    horizontalOffset = rootBounds.getX() + fullWidth - buttonWidth;
    verticalOffset = rootBounds.getY();
    
    //int buttonHeight = (rowHeight * 2) + vspacing; // spans two rows
    Rectangle<int> buttonBounds(horizontalOffset, verticalOffset, buttonWidth, rowHeight);
    deleteButton.setBounds(buttonBounds);
    
}