Exemplo n.º 1
0
void AquariaComboBox::setSelectedItem(int index)
{
	if (isopen) close();

	if (index == AQUARIACOMBOBOXITEM_UP)
	{
		doScroll(1);
	}
	else if (index == AQUARIACOMBOBOXITEM_DOWN)
	{
		doScroll(0);
	}
	else
	{
		if (index >= 0 && index < items.size())
		{
			selectedItem = index;
			selectedItemLabel->setText(items[index]);
			scroll = index;
			if (scroll + numDrops > items.size())
			{
				if (items.size() < numDrops)
					scroll = 0;
				else
					scroll = items.size() - numDrops;
			}
		}
	}
}
Exemplo n.º 2
0
void StGLScrollArea::stglUpdate(const StPointD_t& theCursorZo) {
    if(!isVisible()) {
        StGLWidget::stglUpdate(theCursorZo);
        return;
    }

    if(myIsLeftClick
    && isScrollable()) {
        StPointD_t aDelta = myRoot->getCursorZo() - myClickPntZo;
        double aDeltaY = aDelta.y() * myRoot->getRectPx().height();
        myClickPntZo = myRoot->getCursorZo();

        double aTime = myDragTimer.getElapsedTime();
        if(myDragTimer.isOn()) {
            if(aTime > 0.1) {
                myFlingYSpeed = 0.0;
                myDragYDelta  = 0.0;
                myDragTimer.restart();
            }
            else if(aTime > 0.0000001
                 && std::abs(aDeltaY) >= double(myRoot->scale(2))) {
                if(std::abs(myDragYDelta) < 0.001
                || haveSameSign(myDragYDelta, aDeltaY)) {
                    myFlingYSpeed = (myDragYDelta + aDeltaY) / aTime;
                }
                myDragYDelta = 0.0;
                myDragTimer.restart();
            } else {
                myDragYDelta += aDeltaY;
            }
        } else {
            myFlingYSpeed = 0.0;
            myDragYDelta  = 0.0;
            myDragTimer.restart();
        }
        doScroll((int )aDeltaY);
    } else if(myFlingTimer.isOn()) {
        double aTime = myFlingTimer.getElapsedTime();
        double anA   = (myFlingYSpeed > 0.0 ? -1.0 : 1.0) * myFlingAccel;
        int aFullDeltaY = int(myFlingYSpeed * aTime + anA * aTime * aTime);
        int aDeltaY     = aFullDeltaY - myFlingYDone;
        if(aDeltaY == 0) {
            // ignore zero update
        } else if(!haveSameSign(myFlingYSpeed, aDeltaY)) {
            myFlingTimer.stop();
        } else  {
            myFlingYDone += aDeltaY;
            doScroll(aDeltaY, true);
        }
    }

    StGLWidget::stglUpdate(theCursorZo);
}
Exemplo n.º 3
0
bool StGLScrollArea::doScroll(const StScrollEvent& theEvent) {
    if(StGLWidget::doScroll(theEvent)) {
        return true;
    }

    int aDeltaY = (int )fabs(theEvent.DeltaY * 2.0f);
    if(theEvent.DeltaY > 0.001f) {
        doScroll( myRoot->scale(aDeltaY));
    } else if(theEvent.DeltaY < -0.001f) {
        doScroll(-myRoot->scale(aDeltaY));
    }
    return true;
}
Exemplo n.º 4
0
/* ******************************************************************** *
 * public: button up down left right were pressed 
 * @param
 *		(u)p (d)own (l)eft (r)ight status (uint8)
 * @return
 * ******************************************************************** */
void	LCDMenuLib::Button_udlr(uint8_t but)
/* ******************************************************************** */
{		
	if (function == _LCDML_NO_FUNC) {	//check menu lock	
		//enable up and down button for menu mode and scroll		
		switch(but)
		{
			case _LCDML_button_up:   
                if (curloc > 0) 		 
                { 
                    curloc--; 
                    doScroll();
                } 
                else 
                {
                    if(bitRead(control2, _LCDML_control2_rollover))
                    {
                        // jump to the end of the menu
                        curloc = child_cnt;
                        if(child_cnt-rows < 0) {
                            scroll = 0;
                        } else {
                            scroll = child_cnt-rows;
                        }                    
                        doScroll();
                        display();
                    }
                }
                break;
			case _LCDML_button_down: 
                if (curloc < child_cnt) 
                { 
                    curloc++; 
                    doScroll();
                } else {
                    if(bitRead(control2, _LCDML_control2_rollover))
                    {
                        // jump to the first line
                        curloc = 0;
                        scroll = 0;                
                        doScroll();
                        display();                
                    }
                }
                break;
		}		
	}
	else {
		bitSet(button, but);
	}			
}
Exemplo n.º 5
0
/* ******************************************************************** *
 * public: button up down left right were pressed 
 * @param
 *		(u)p (d)own (l)eft (r)ight status (uint8)
 * @return
 * ******************************************************************** */
void	LCDMenuLib::Button_udlr(uint8_t but)
/* ******************************************************************** */
{		
	if (function == _LCDML_NO_FUNC) {	//check menu lock	
		//enable up and down button for menu mode and scroll		
		switch(but)
		{
			case _LCDML_button_up:   if (curloc > 0) 		 { curloc--; doScroll();} break;
			case _LCDML_button_down: if (curloc < child_cnt) { curloc++; doScroll();} break;
		}		
	}
	else {
		bitSet(button, but);
	}			
}
Exemplo n.º 6
0
void Editor::updateCaret()
{
  placeCaret();

  POINT pt = toPoint(caret);
  caretX = pt.x;
  SCROLLINFO si;
  memset(&si, 0, sizeof si);
  si.cbSize = sizeof si;
  si.fMask = SIF_RANGE | SIF_PAGE;

  int xto = scrollPos.x;
  GetScrollInfo(hWnd, SB_HORZ, &si);
  if (pt.x < scrollPos.x)
    xto = (pt.x > 2 ? pt.x - 2 : 0);
  else if (pt.x >= scrollPos.x + si.nPage)
    xto = (pt.x - si.nPage + 10 < si.nMax ? pt.x - si.nPage + 10 : si.nMax);

  int yto = scrollPos.y;
  GetScrollInfo(hWnd, SB_VERT, &si);
  if (pt.y < scrollPos.y)
    yto = (pt.y > 2 ? pt.y - 2 : 0);
  else if (pt.y >= scrollPos.y + si.nPage)
    yto = (pt.y - si.nPage + 10 < si.nMax ? pt.y - si.nPage + 10 : si.nMax);

  doScroll(xto, yto);
  updateFocus();
  invalidate();
}
Exemplo n.º 7
0
void AquariaComboBox::setSelectedItem(int index)
{
	if (isopen) close();

	selectedItem = index;

	if (index == AQUARIACOMBOBOXITEM_UP)
	{
		doScroll(1);
	}
	else if (index == AQUARIACOMBOBOXITEM_DOWN)
	{
		doScroll(0);
	}
	else
	{
		if (index >= 0 && index < items.size())
			selectedItemLabel->setText(items[index]);
	}
}
Exemplo n.º 8
0
void
BScrollBar::MouseUp(BPoint where)
{
	if (!fTracking) return;
	fTracking = false;

	if (fTrackingState != 0) {
		int8 state = fTrackingState;
		fTrackingState = 0;
		Invalidate();

		doScroll(state);
	}
}
Exemplo n.º 9
0
ResultsView::ResultsView( QWidget *parent, const char *name )
: KHTMLPart( parent, parent )
, _scrollValue( 0 )
{
  ////////setReadOnly(true);
  /* TODO: configurably underlined links */
//	setLinkUnderline(false); //KDE4 CHANGE
  ////////basicMode = false;

  // don't let ktextbrowser internally handle link clicks
  ////////setNotifyClick(true);
  connect( view(), SIGNAL(finishedLayout()),
             this,   SLOT(doScroll()) );
}
Exemplo n.º 10
0
void
BScrollBar::MouseDown(BPoint where)
{
	if (fRangeMin == fRangeMax || IsEnabled() == false || !QueryCurrentMouse(true, B_PRIMARY_MOUSE_BUTTON)) return;

	BRect rect = VisibleBounds();
	if (!rect.Contains(where)) return;

	if (fTrackingState != 0) return;
	e_theme_engine *theme = get_current_theme_engine();
	if (theme == NULL || theme->get_scrollbar_respondent_region == NULL) return;
	BRegion dragTo, smallUp, smallDown, largeUp, largeDown;
	theme->get_scrollbar_respondent_region(theme, this, Frame().OffsetToSelf(B_ORIGIN),
	                                       fOrientation, fRangeMin, fRangeMax, fValue, NULL,
	                                       &dragTo, &smallUp, &smallDown, &largeUp, &largeDown);
	if (smallUp.Contains(where)) {
		fTrackingState = 1;
		fTrackingRegion = smallUp;
	} else if (smallDown.Contains(where)) {
		fTrackingState = 2;
		fTrackingRegion = smallDown;
	} else if (largeUp.Contains(where)) {
		fTrackingState = 3;
		fTrackingRegion = largeUp;
	} else if (largeDown.Contains(where)) {
		fTrackingState = 4;
		fTrackingRegion = largeDown;
	} else if (dragTo.Contains(where)) {
		fTrackingState = 5;
		fTrackingRegion = dragTo;
	} else fTrackingRegion.MakeEmpty();
	if (fTrackingState == 0) return;

	if (!fTracking) fTracking = true;
	fMousePosition = where;

	if (SetPrivateEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS) != B_OK) {
		Invalidate();
		Window()->UpdateIfNeeded();
		e_snooze(50000);
		fTracking = false;
		int8 state = fTrackingState;
		fTrackingState = 0;
		Invalidate();
		doScroll(state);
	} else {
		Invalidate();
	}
}
Exemplo n.º 11
0
void MainWindow::addToStatusList(bool in, QString msg)
{
    msg.trimmed();
    msg.remove('\r');
    msg.remove('\n');

    if (msg.length() == 0)
        return;

    QString nMsg(msg);
    if (!in)
        nMsg = "> " + msg;
    ui->statusList->addItem(nMsg);

    status("%s", nMsg.toLocal8Bit().constData());

    doScroll();
}
Exemplo n.º 12
0
/* ******************************************************************** *
 * private: go in a menu item and display next elements
 * @param
 *		pointer to next menu item
 * @return
 * ******************************************************************** */
void	LCDMenuLib::goMenu(LCDMenu &m)
/* ******************************************************************** */
{
	//declare variables
	int diff;
    scroll = 0;

	//set current menu object	
	curMenu=&m;	
		
	if(layer < _LCDML_DISP_cfg_cursor_deep) { //check layer deep		
		if(bitRead(control, _LCDML_control_menu_back) == 0) { //check back button		
			//go into the next layer
			layer_save[layer] = curloc;
			layer++;		
			curloc = 0;
		} 
		else {
			//button reset
			bitWrite(control, _LCDML_control_menu_back, 0);
			
			if(layer > 0) {				
				layer--;				
				curloc = layer_save[layer];

				if(curloc >= rows) {
					diff = curloc-(rows-1);
					for(int i=0; i<diff; i++) 
					{						
						doScroll();
					}
				}
			}
		}
	}
	display();	
}
Exemplo n.º 13
0
void LCDMenu2::goMenu(Menu &m)
{
    curMenu=&m;

    if(layer < 8) {
        int diff;
        scroll = 0;

        if(back == 0) {
            layer_save[layer] = curloc;
            layer++;
            curloc = 0;
        } else {
            back = 0;

            if(layer > 0) {
                layer--;
                curloc = layer_save[layer];

                if(curloc >= rows) {
                    diff = curloc-(rows-1);
                    for(int i=0; i<diff; i++) {
                        doScroll();
                    }
                }
            }
        }
    }


    if(layer >= 0 && layer <5) {
      funcname[layer-1] = curMenu->name;
    }


    display();
}
Exemplo n.º 14
0
void LCDMenu::goDown()
{
curloc+=prow;
doScroll();
}
Exemplo n.º 15
0
void AquariaComboBox::onUpdate(float dt)
{
	RenderObject::onUpdate(dt);

	if (alpha.x < 1)
		return;

	//window->alpha.interpolateTo(1, 0.2);

	if (enqueuedSelectItem != -1)
	{
		setSelectedItem(enqueuedSelectItem);
		enqueuedSelectItem = -1;
	}

	scrollDelay -= dt;
	if (scrollDelay < 0) scrollDelay = 0;

	if (isopen)
	{
		if (!core->mouse.buttons.left)
		{
			firstScroll = 1;
			scrollDelay = 0;
		}

		if (core->mouse.buttons.left && scrollBtnDown->isCoordinateInsideWorldRect(core->mouse.position, 20, 32))
		{
			if (scrollDelay == 0)
			{
				doScroll(1);

				if (firstScroll)
				{
					scrollDelay = SCROLL_DELAY_FIRST;
					firstScroll = 0;
				}
				else
				{
					scrollDelay = SCROLL_DELAY;
				}
			}
			scrollBtnDown->setTexture("gui/combo-button-down");
		}
		else
		{
			scrollBtnDown->setTexture("gui/combo-button-up");
		}

		if (core->mouse.buttons.left && scrollBtnUp->isCoordinateInsideWorldRect(core->mouse.position, 20, 32))
		{
			if (scrollDelay == 0)
			{
				doScroll(0);

				if (firstScroll)
				{
					scrollDelay = SCROLL_DELAY_FIRST;
					firstScroll = 0;
				}
				else
				{
					scrollDelay = SCROLL_DELAY;
				}
			}
			scrollBtnUp->setTexture("gui/combo-button-down");
		}
		else
		{
			scrollBtnUp->setTexture("gui/combo-button-up");
		}
	}



	if (bar->isCoordinateInsideWorld(core->mouse.position))
	{
		if (!mb && core->mouse.buttons.left)
		{
			mb = true;
		}
		else if (mb && !core->mouse.buttons.left)
		{
			mb = false;

			core->sound->playSfx("click");

			if (isopen)
				close();
			else
				open();
		}
	}
	else
	{
		mb = false;
	}

	if (isopen)
	{
		if (core->mouse.scrollWheelChange > 0)
		{
			doScroll(0);
		}
		else if (core->mouse.scrollWheelChange < 0)
		{
			doScroll(1);
		}
	}

}
Exemplo n.º 16
0
void LCDMenu::goRight()
{
curloc++;
doScroll();
}
Exemplo n.º 17
0
void LCDMenu2::goDown()
{
    curloc+=1;
    doScroll();
}
Exemplo n.º 18
0
void LCDMenu2::goUp()
{
    curloc-=1;
    doScroll();
}
Exemplo n.º 19
0
void LCDMenu::goLeft()
{
curloc--;
doScroll();
}
Exemplo n.º 20
0
void LCDMenu::goUp()
{
curloc-=prow;
doScroll();
}
Exemplo n.º 21
0
void FrameGdk::handleGdkEvent(GdkEvent* event)
{
    switch (event->type) {
        case GDK_EXPOSE: {
            GdkRectangle clip;
            gdk_region_get_clipbox(event->expose.region, &clip);
            gdk_window_begin_paint_region (event->any.window, event->expose.region);
            cairo_t* cr = gdk_cairo_create (event->any.window);
            GraphicsContext* ctx = new GraphicsContext(cr);
            paint(ctx, IntRect(clip.x, clip.y, clip.width, clip.height));
            delete ctx;
            gdk_window_end_paint (event->any.window);
            break;
        }
        case GDK_SCROLL: {
            PlatformWheelEvent wheelEvent(event);
            view()->handleWheelEvent(wheelEvent);
            if (wheelEvent.isAccepted()) {
                return;
            }
            RenderObject::NodeInfo nodeInfo(true, true);
            renderer()->layer()->hitTest(nodeInfo, wheelEvent.pos());
            Node* node = nodeInfo.innerNode();
            if (!node)
                return;
            //Default to scrolling the page
            //not sure why its null
            //broke anyway when its not null
            doScroll(renderer(), wheelEvent.isHorizontal(), wheelEvent.delta());
            break;
        }
        case GDK_DRAG_ENTER:
        case GDK_DRAG_LEAVE:
        case GDK_DRAG_MOTION:
        case GDK_DRAG_STATUS:
        case GDK_DROP_START:
        case GDK_DROP_FINISHED: {
            //bool updateDragAndDrop(const PlatformMouseEvent&, Clipboard*);
            //void cancelDragAndDrop(const PlatformMouseEvent&, Clipboard*);
            //bool performDragAndDrop(const PlatformMouseEvent&, Clipboard*);
            break;
        }
        case GDK_MOTION_NOTIFY:
            view()->handleMouseMoveEvent(event);
            break;
        case GDK_BUTTON_PRESS:
        case GDK_2BUTTON_PRESS:
        case GDK_3BUTTON_PRESS:
            view()->handleMousePressEvent(event);
            break;
        case GDK_BUTTON_RELEASE:
            view()->handleMouseReleaseEvent(event);
            break;
        case GDK_KEY_PRESS:
        case GDK_KEY_RELEASE: {
            PlatformKeyboardEvent kevent(event);
            bool handled = false;
            if (!kevent.isKeyUp()) {
                Node* start = selection().start().node();
                if (start && start->isContentEditable()) {
                    switch(kevent.WindowsKeyCode()) {
                        case VK_BACK:
                            TypingCommand::deleteKeyPressed(document());
                            break;
                        case VK_DELETE:
                            TypingCommand::forwardDeleteKeyPressed(document());
                            break;
                        case VK_LEFT:
                            selection().modify(SelectionController::MOVE, SelectionController::LEFT, CharacterGranularity);
                            break;
                        case VK_RIGHT:
                            selection().modify(SelectionController::MOVE, SelectionController::RIGHT, CharacterGranularity);
                            break;
                        case VK_UP:
                            selection().modify(SelectionController::MOVE, SelectionController::BACKWARD, ParagraphGranularity);
                            break;
                        case VK_DOWN:
                            selection().modify(SelectionController::MOVE, SelectionController::FORWARD, ParagraphGranularity);
                            break;
                        default:
                            TypingCommand::insertText(document(), kevent.text(), false);

                    }
                    handled = true;
                }
                if (!handled) {
                    switch (kevent.WindowsKeyCode()) {
                        case VK_LEFT:
                            doScroll(renderer(), true, -120);
                            break;
                        case VK_RIGHT:
                            doScroll(renderer(), true, 120);
                            break;
                        case VK_UP:
                            doScroll(renderer(), false, -120);
                            break;
                        case VK_PRIOR:
                            //return SB_PAGEUP;
                            break;
                        case VK_NEXT:
                            //return SB_PAGEDOWN;
                            break;
                        case VK_DOWN:
                            doScroll(renderer(), false, 120);
                            break;
                        case VK_HOME:
                            renderer()->layer()->scrollToOffset(0, 0, true, true);
                            doScroll(renderer(), false, 120);
                            break;
                        case VK_END:
                            renderer()->layer()->scrollToOffset(0,
                                                                renderer()->height(), true, true);
                            break;
                        case VK_SPACE:
                            if (kevent.shiftKey())
                                doScroll(renderer(), false, -120);
                            else
                                doScroll(renderer(), false, 120);
                            break;
                    }

                }
            }
        }
        default:
            break;
    }
}
Exemplo n.º 22
0
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
   // open_button_text(tr(OPEN_BUTTON_TEXT)),
   // close_button_text(tr(CLOSE_BUTTON_TEXT)),
    open_button_text(tr("Open")),
    close_button_text(tr("Close / Reset")),
    absoluteAfterAxisAdj(false),
    checkLogWrite(false),
    sliderPressed(false),
    sliderTo(0.0),
    sliderZCount(0),
    scrollRequireMove(true), scrollPressed(false)
{
    // Setup our application information to be used by QSettings
    QCoreApplication::setOrganizationName(COMPANY_NAME);
    QCoreApplication::setOrganizationDomain(DOMAIN_NAME);
    QCoreApplication::setApplicationName(APPLICATION_NAME);

    // required if passing the object by reference into signals/slots
    qRegisterMetaType<Coord3D>("Coord3D");
    qRegisterMetaType<PosItem>("PosItem");
    qRegisterMetaType<ControlParams>("ControlParams");


    ui->setupUi(this);

    readSettings();

    info("%s has started", GRBL_CONTROLLER_NAME_AND_VERSION);

    // see http://blog.qt.digia.com/2010/06/17/youre-doing-it-wrong/
    // The thread points out that the documentation for QThread is wrong :) and
    // you should NOT subclass from QThread and override run(), rather,
    // attach your QOBJECT to a thread and use events (signals/slots) to communicate.
    gcode.moveToThread(&gcodeThread);
    runtimeTimer.moveToThread(&runtimeTimerThread);

    ui->lcdWorkNumberX->setDigitCount(8);
    ui->lcdMachNumberX->setDigitCount(8);
    ui->lcdWorkNumberY->setDigitCount(8);
    ui->lcdMachNumberY->setDigitCount(8);
    ui->lcdWorkNumberZ->setDigitCount(8);
    ui->lcdMachNumberZ->setDigitCount(8);
	ui->lcdWorkNumberC->setDigitCount(8);
    ui->lcdMachNumberC->setDigitCount(8);

    if (!controlParams.useFourAxis)
    {
        ui->DecCBtn->hide();
        ui->IncCBtn->hide();
        ui->lblCJog->hide();
        ui->lcdWorkNumberC->hide();
        ui->lcdWorkNumberC->setAttribute(Qt::WA_DontShowOnScreen, true);
        ui->lcdMachNumberC->hide();
        ui->lcdMachNumberC->setAttribute(Qt::WA_DontShowOnScreen, true);
        ui->lblC->hide();
        ui->lblC->setAttribute(Qt::WA_DontShowOnScreen, true);
    }

    //buttons
    connect(ui->btnOpenPort,SIGNAL(clicked()),this,SLOT(openPort()));
    connect(ui->btnGRBL,SIGNAL(clicked()),this,SLOT(setGRBL()));
    connect(ui->DecXBtn,SIGNAL(clicked()),this,SLOT(decX()));
    connect(ui->DecYBtn,SIGNAL(clicked()),this,SLOT(decY()));
    connect(ui->DecZBtn,SIGNAL(clicked()),this,SLOT(decZ()));
    connect(ui->IncXBtn,SIGNAL(clicked()),this,SLOT(incX()));
    connect(ui->IncYBtn,SIGNAL(clicked()),this,SLOT(incY()));
    connect(ui->IncZBtn,SIGNAL(clicked()),this,SLOT(incZ()));
	connect(ui->DecCBtn,SIGNAL(clicked()),this,SLOT(decC()));
    connect(ui->IncCBtn,SIGNAL(clicked()),this,SLOT(incC()));
    connect(ui->btnSetHome,SIGNAL(clicked()),this,SLOT(setHome()));
    connect(ui->comboCommand->lineEdit(),SIGNAL(editingFinished()),this,SLOT(gotoXYZC()));
    connect(ui->Begin,SIGNAL(clicked()),this,SLOT(begin()));
    connect(ui->openFile,SIGNAL(clicked()),this,SLOT(openFile()));
    connect(ui->Stop,SIGNAL(clicked()),this,SLOT(stop()));
    connect(ui->SpindleOn,SIGNAL(toggled(bool)),this,SLOT(toggleSpindle()));
    connect(ui->chkRestoreAbsolute,SIGNAL(toggled(bool)),this,SLOT(toggleRestoreAbsolute()));
    connect(ui->actionOptions,SIGNAL(triggered()),this,SLOT(getOptions()));
    connect(ui->actionExit,SIGNAL(triggered()),this,SLOT(close()));
    connect(ui->actionAbout,SIGNAL(triggered()),this,SLOT(showAbout()));
    connect(ui->btnResetGrbl,SIGNAL(clicked()),this,SLOT(grblReset()));
    connect(ui->btnUnlockGrbl,SIGNAL(clicked()),this,SLOT(grblUnlock()));
    connect(ui->btnGoHomeSafe,SIGNAL(clicked()),this,SLOT(goHomeSafe()));
    connect(ui->verticalSliderZJog,SIGNAL(valueChanged(int)),this,SLOT(zJogSliderDisplay(int)));
    connect(ui->verticalSliderZJog,SIGNAL(sliderPressed()),this,SLOT(zJogSliderPressed()));
    connect(ui->verticalSliderZJog,SIGNAL(sliderReleased()),this,SLOT(zJogSliderReleased()));

    connect(this, SIGNAL(sendFile(QString)), &gcode, SLOT(sendFile(QString)));
    connect(this, SIGNAL(openPort(QString,QString)), &gcode, SLOT(openPort(QString,QString)));
    connect(this, SIGNAL(closePort(bool)), &gcode, SLOT(closePort(bool)));
    connect(this, SIGNAL(sendGcode(QString)), &gcode, SLOT(sendGcode(QString)));
    connect(this, SIGNAL(gotoXYZC(QString)), &gcode, SLOT(gotoXYZC(QString)));
    connect(this, SIGNAL(axisAdj(char, float, bool, bool, int)), &gcode, SLOT(axisAdj(char, float, bool, bool, int)));
    connect(this, SIGNAL(setResponseWait(ControlParams)), &gcode, SLOT(setResponseWait(ControlParams)));
    connect(this, SIGNAL(shutdown()), &gcodeThread, SLOT(quit()));
    connect(this, SIGNAL(shutdown()), &runtimeTimerThread, SLOT(quit()));
    connect(this, SIGNAL(setProgress(int)), ui->progressFileSend, SLOT(setValue(int)));
    connect(this, SIGNAL(setRuntime(QString)), ui->outputRuntime, SLOT(setText(QString)));
    connect(this, SIGNAL(sendSetHome()), &gcode, SLOT(grblSetHome()));
    connect(this, SIGNAL(sendGrblReset()), &gcode, SLOT(sendGrblReset()));
    connect(this, SIGNAL(sendGrblUnlock()), &gcode, SLOT(sendGrblUnlock()));
    connect(this, SIGNAL(goToHome()), &gcode, SLOT(goToHome()));
    connect(this, SIGNAL(setItems(QList<PosItem>)), ui->wgtVisualizer, SLOT(setItems(QList<PosItem>)));

    connect(&gcode, SIGNAL(sendMsg(QString)),this,SLOT(receiveMsg(QString)));
    connect(&gcode, SIGNAL(portIsClosed(bool)), this, SLOT(portIsClosed(bool)));
    connect(&gcode, SIGNAL(portIsOpen(bool)), this, SLOT(portIsOpen(bool)));
    connect(&gcode, SIGNAL(addList(QString)),this,SLOT(receiveList(QString)));
    connect(&gcode, SIGNAL(addListFull(QStringList)),this,SLOT(receiveListFull(QStringList)));
    connect(&gcode, SIGNAL(addListOut(QString)),this,SLOT(receiveListOut(QString)));
    connect(&gcode, SIGNAL(stopSending()), this, SLOT(stopSending()));
    connect(&gcode, SIGNAL(setCommandText(QString)), ui->comboCommand->lineEdit(), SLOT(setText(QString)));
    connect(&gcode, SIGNAL(setProgress(int)), ui->progressFileSend, SLOT(setValue(int)));
    connect(&gcode, SIGNAL(adjustedAxis()), this, SLOT(adjustedAxis()));
    connect(&gcode, SIGNAL(resetTimer(bool)), &runtimeTimer, SLOT(resetTimer(bool)));
    connect(&gcode, SIGNAL(enableGrblDialogButton()), this, SLOT(enableGrblDialogButton()));
    connect(&gcode, SIGNAL(updateCoordinates(Coord3D,Coord3D)), this, SLOT(updateCoordinates(Coord3D,Coord3D)));
    connect(&gcode, SIGNAL(setLastState(QString)), ui->outputLastState, SLOT(setText(QString)));
    connect(&gcode, SIGNAL(setUnitsWork(QString)), ui->outputUnitsWork, SLOT(setText(QString)));
    connect(&gcode, SIGNAL(setUnitsMachine(QString)), ui->outputUnitsMachine, SLOT(setText(QString)));
    connect(&gcode, SIGNAL(setLivePoint(double, double, bool)), ui->wgtVisualizer, SLOT(setLivePoint(double, double, bool)));
    connect(&gcode, SIGNAL(setVisCurrLine(int)), ui->wgtVisualizer, SLOT(setVisCurrLine(int)));

    connect(&runtimeTimer, SIGNAL(setRuntime(QString)), ui->outputRuntime, SLOT(setText(QString)));

	// This code generates too many messages and chokes operation on raspberry pi. Do not use.
    //connect(ui->statusList->model(), SIGNAL(rowsInserted(const QModelIndex&, int, int)), ui->statusList, SLOT(scrollToBottom()));

	// instead, use this one second timer-based approach
    scrollTimer = new QTimer(this);
    connect(scrollTimer, SIGNAL(timeout()), this, SLOT(doScroll()));
    scrollTimer->start(1000);
    connect(ui->statusList->verticalScrollBar(), SIGNAL(sliderPressed()), this, SLOT(statusSliderPressed()));
    connect(ui->statusList->verticalScrollBar(), SIGNAL(sliderReleased()), this, SLOT(statusSliderReleased()));

    runtimeTimerThread.start();
    gcodeThread.start();

    ui->comboStep->addItem("0.01");
    ui->comboStep->addItem("0.1");
    ui->comboStep->addItem("1");
    ui->comboStep->addItem("10");
	ui->comboStep->addItem("100");
    ui->comboStep->setCurrentIndex(3);

	// Don't use - it will not show horizontal scrollbar for small app size
    //ui->statusList->setUniformItemSizes(true);

	// Does not work correctly for horizontal scrollbar:
    //MyItemDelegate *scrollDelegate = new MyItemDelegate(ui->statusList);
    //scrollDelegate->setWidth(600);
    //ui->statusList->setItemDelegate(scrollDelegate);

    scrollStatusTimer.start();

    // Cool utility class off Google code that enumerates COM ports in platform-independent manner
    QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();

    int portIndex = -1;
    for (int i = 0; i < ports.size(); i++)
    {
        ui->cmbPort->addItem(ports.at(i).portName.toLocal8Bit().constData());

        if (ports.at(i).portName == lastOpenPort)
            portIndex = i;

        //diag("port name: %s\n", ports.at(i).portName.toLocal8Bit().constData());
        //diag("friendly name: %s\n", ports.at(i).friendName.toLocal8Bit().constData());
        //diag("physical name: %s\n", ports.at(i).physName.toLocal8Bit().constData());
        //diag("enumerator name: %s\n", ports.at(i).enumName.toLocal8Bit().constData());
        //diag("===================================\n\n");
    }

    if (portIndex >= 0)
    {
        // found matching port
        ui->cmbPort->setCurrentIndex(portIndex);
    }
    else if (lastOpenPort.size() > 0)
    {
        // did not find matching port
        // This code block is used to restore a port to view that isn't visible to QextSerialEnumerator
        ui->cmbPort->addItem(lastOpenPort.toLocal8Bit().constData());
        if (ports.size() > 0)
            ui->cmbPort->setCurrentIndex(ports.size());
        else
            ui->cmbPort->setCurrentIndex(0);
    }

    int baudRates[] = { 9600, 19200, 38400, 57600, 115200 };
    int baudRateCount = sizeof baudRates / sizeof baudRates[0];
    int baudRateIndex = 0;
    for (int i = 0; i < baudRateCount; i++)
    {
        QString baudRate = QString::number(baudRates[i]);
        ui->comboBoxBaudRate->addItem(baudRate);
        if (baudRate == lastBaudRate)
        {
            baudRateIndex = i;
        }
    }

    ui->comboBoxBaudRate->setCurrentIndex(baudRateIndex);

    ui->tabAxisVisualizer->setEnabled(false);
    if (!controlParams.useFourAxis)
    {
        ui->lcdWorkNumberC->setEnabled(false);;
        ui->lcdMachNumberC->setEnabled(false);;
        ui->IncCBtn->setEnabled(false);
        ui->DecCBtn->setEnabled(false);
        ui->lblCJog->setEnabled(false);
    }
    ui->groupBoxSendFile->setEnabled(true);
    ui->comboCommand->setEnabled(false);
    ui->labelCommand->setEnabled(false);
    ui->Begin->setEnabled(false);
    ui->Stop->setEnabled(false);
    ui->progressFileSend->setEnabled(false);
    ui->outputRuntime->setEnabled(false);
    ui->labelRuntime->setEnabled(false);
    ui->btnGRBL->setEnabled(false);
    ui->btnSetHome->setEnabled(false);
    ui->btnResetGrbl->setEnabled(false);
    ui->btnUnlockGrbl->setEnabled(false);
    ui->btnGoHomeSafe->setEnabled(false);
    styleSheet = ui->btnOpenPort->styleSheet();
    ui->statusList->setEnabled(true);
    ui->openFile->setEnabled(true);

    this->setWindowTitle(GRBL_CONTROLLER_NAME_AND_VERSION);
    this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);

    QSettings settings;
    QString useAggrPreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value<QString>();
    controlParams.useAggressivePreload = useAggrPreload == "true";

    if (!controlParams.useAggressivePreload && !promptedAggrPreload)
    {
        QMessageBox msgBox;
        msgBox.setText(tr("You appear to have upgraded to the latest version of Grbl Controller. "
                       "Please be aware that as of version 3.4 the default behavior of sending commands "
                       "to Grbl has been changed to send them as fast as possible (Aggressive preload mode).\n\n"
                       "Your settings have been changed to enable this mode. Why? Because it provides the most "
                       "optimal use of Grbl and greatly reduces the time to finish a typical job.\n\n"
                       "What does this mean to you? "
                       "Arc commands will now run smoother and faster than before, which may "
                       "cause your spindle to work slightly harder, so please run some tests first. "
                       "Alternately, go to the Options dialog and manually disable Aggressive Preload") );
        msgBox.exec();

        controlParams.useAggressivePreload = true;
        settings.setValue(SETTINGS_USE_AGGRESSIVE_PRELOAD, controlParams.useAggressivePreload);
    }

    promptedAggrPreload = true;

    emit setResponseWait(controlParams);
}
Exemplo n.º 23
0
uint32 Editor::onMessage(uint32 message, uint32 wParam, uint32 lParam)
{
  switch (message)
  {
  case WM_DESTROY:
    delete target;
    target = NULL;
    break;
  case WM_SETCURSOR:
    if (LOWORD(lParam) == HTCLIENT)
    {
      POINT pt;
      GetCursorPos(&pt);
      ScreenToClient(hWnd, &pt);
      if (pt.x < LeftMargin())
        SetCursor(cursors[cArrow]);
      else if (selStart != caret)
      {
        pt.x = (pt.x - LeftMargin()) / chSize.cx + scrollPos.x;
        pt.y = pt.y / chSize.cy + scrollPos.y;
        if (pt.y < 0 || pt.y >= lines.length() || pt.x < 0 || pt.x >= lines[pt.y].text.length())
          SetCursor(cursors[cBeam]);
        else
        {
          int offset = fromPoint(pt);
          int sela = (selStart < caret ? selStart : caret);
          int selb = (selStart < caret ? caret : selStart);
          if (offset >= sela && offset < selb)
            SetCursor(cursors[cArrow]);
          else
            SetCursor(cursors[cBeam]);
        }
      }
      else
        SetCursor(cursors[cBeam]);
    }
    else
      SetCursor(cursors[cArrow]);
    return TRUE;
  case WM_ERASEBKGND:
    return TRUE;
  case WM_PAINT:
    paint();
    return 0;
  case WM_SIZE:
    if (hBitmap)
    {
      int wd = LOWORD(lParam);
      int ht = HIWORD(lParam);
      if (wd < 10) wd = 10;
      if (ht < 10) ht = 10;
      hBitmap = CreateCompatibleBitmap(hDC, wd, ht);
      SelectObject(hDC, hBitmap);
    }
    updateExtent();
    return 0;
  case WM_SETFOCUS:
    placeCaret();
    invalidate();
    getParent()->notify(EN_FOCUSED, (uint32) this, 0);
    return 0;
  case WM_KILLFOCUS:
    DestroyCaret();
    updateCaret();
    invalidate();
    return 0;
  case WM_LBUTTONDBLCLK:
    {
      POINT pt = paramToPoint(lParam);
      fixPoint(pt);
      int ptStart = wordEnd(lines[pt.y].text.c_str(), pt.x, -1);
      int ptEnd = wordEnd(lines[pt.y].text.c_str(), pt.x, 1);
      int offset = fromPoint(pt);
      selStart = offset - (pt.x - ptStart);
      caret = offset + (ptEnd - pt.x);
      updateCaret();
    }
    return 0;
  case WM_LBUTTONDOWN:
    if (int(GET_X_LPARAM(lParam)) < int(settings->bpOffset - scrollPos.x * chSize.cx))
    {
      POINT pt = paramToPoint(lParam);
      toggleBreakpoint(pt.y);
    }
    else
    {
      POINT pt = paramToPoint(lParam);
      int offset = fromPoint(pt);
      int sela = (selStart < caret ? selStart : caret);
      int selb = (selStart > caret ? selStart : caret);
      if (offset >= sela && offset < selb)
      {
        dragop = 1;
        uint32 fx = DoDragDropEx(CF_UNICODETEXT, CreateGlobalText(getSelection()),
            DROPEFFECT_MOVE | DROPEFFECT_COPY, hWnd);
        if (fx == DROPEFFECT_NONE)
          dragop = 0;
        //else if (fx != DROPEFFECT_COPY && dragop != 2)
        //  replace(sela, selb, "");
      }
      else
        SetCapture(hWnd);
      if (dragop == 0)
      {
        caret = offset;
        if (!(wParam & MK_SHIFT))
          selStart = caret;
      }
      dragop = 0;
      if (GetFocus() != hWnd)
        SetFocus(hWnd);
      updateCaret();
    }
    return 0;
  case WM_RBUTTONDOWN:
    if (int(GET_X_LPARAM(lParam)) >= int(settings->bpOffset - scrollPos.x * chSize.cx))
    {
      POINT pt = paramToPoint(lParam);
      int offset = fromPoint(pt);
      int sela = (selStart < caret ? selStart : caret);
      int selb = (selStart > caret ? selStart : caret);
      if (offset < sela || offset >= selb)
        caret = selStart = offset;
      if (GetFocus() != hWnd)
        SetFocus(hWnd);
      updateCaret();
    }
    return 0;
  case WM_MOUSEMOVE:
    if (GetCapture() == hWnd && (wParam & MK_LBUTTON))
    {
      POINT pt = paramToPoint(lParam);
      caret = fromPoint(pt);
      updateCaret();
    }
    return 0;
  case WM_LBUTTONUP:
    ReleaseCapture();
    return 0;
  case WM_CHAR:
    if (iswprint(wParam) && (GetAsyncKeyState(VK_CONTROL) & 0x8000) == 0)
    {
      if (caret == selStart && !insertMode && caret < getTextLength())
        replace(caret, caret + 1, WideString((wchar_t) wParam));
      else
        replace(selStart, caret, WideString((wchar_t) wParam));
    }
    return 0;
  case WM_VSCROLL:
    {
      SCROLLINFO si;
      memset(&si, 0, sizeof si);
      si.cbSize = sizeof si;
      si.fMask = SIF_ALL;
      GetScrollInfo(hWnd, SB_VERT, &si);
      switch (LOWORD(wParam))
      {
      case SB_TOP:
        si.nPos = si.nMin;
        break;
      case SB_BOTTOM:
        si.nPos = si.nMax;
        break;
      case SB_LINEUP:
        si.nPos--;
        break;
      case SB_LINEDOWN:
        si.nPos++;
        break;
      case SB_PAGEUP:
        si.nPos -= si.nPage;
        break;
      case SB_PAGEDOWN:
        si.nPos += si.nPage;
        break;
      case SB_THUMBTRACK:
        si.nPos = si.nTrackPos;
        break;
      }
      doScroll(scrollPos.x, si.nPos);
    }
    return 0;
  case WM_HSCROLL:
    {
      SCROLLINFO si;
      memset(&si, 0, sizeof si);
      si.cbSize = sizeof si;
      si.fMask = SIF_ALL;
      GetScrollInfo(hWnd, SB_HORZ, &si);
      switch (LOWORD(wParam))
      {
      case SB_LEFT:
        si.nPos = si.nMin;
        break;
      case SB_RIGHT:
        si.nPos = si.nMax;
        break;
      case SB_LINELEFT:
        si.nPos--;
        break;
      case SB_LINERIGHT:
        si.nPos++;
        break;
      case SB_PAGELEFT:
        si.nPos -= si.nPage;
        break;
      case SB_PAGERIGHT:
        si.nPos += si.nPage;
        break;
      case SB_THUMBTRACK:
        si.nPos = si.nTrackPos;
        break;
      }
      doScroll(si.nPos, scrollPos.y);
    }
    return 0;
  case WM_MOUSEWHEEL:
    {
      int step;
      SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &step, 0);
      if (step < 0)
        step = 3;
      scrollAccum.y += GET_WHEEL_DELTA_WPARAM(wParam) * step;
      doScroll(scrollPos.x, scrollPos.y - scrollAccum.y / WHEEL_DELTA);
      scrollAccum.y %= WHEEL_DELTA;
    }
    return 0;
  case WM_MOUSEHWHEEL:
    {
      scrollAccum.x += GET_WHEEL_DELTA_WPARAM(wParam) * 4;
      doScroll(scrollPos.x + scrollAccum.x / WHEEL_DELTA, scrollPos.y);
      scrollAccum.x %= WHEEL_DELTA;
    }
    return 0;
  case WM_DRAGOVER:
    {
      if (running || settings->mode)
        return TRUE;
      POINT pt = paramToPoint(lParam);
      dropPos = fromPoint(pt);

      RECT rc;
      GetClientRect(hWnd, &rc);
      int xto = scrollPos.x;
      if (pt.x < 10)
        xto--;
      else if (pt.x > rc.right - 10)
        xto++;
      int yto = scrollPos.y;
      if (pt.y < 10)
        yto--;
      else if (pt.y > rc.bottom - 10)
        yto++;
      doScroll(xto, yto);

      int sela = (selStart < caret ? selStart : caret);
      int selb = (selStart > caret ? selStart : caret);
      if (dropPos > sela && dropPos < selb)
        return TRUE;
      else
      {
        fixPoint(pt);
        CreateCaret(hWnd, NULL, 2, chSize.cy);
        SetCaretPos((pt.x - scrollPos.x) * chSize.cx + LeftMargin(), (pt.y - scrollPos.y) * chSize.cy);
        ShowCaret(hWnd);
      }
    }
    return 0;
  case WM_DRAGLEAVE:
    dropPos = 0;
    updateCaret();
    return 0;
  case WM_DRAGDROP:
    if (running || settings->mode)
      return DROPEFFECT_NONE;
    if (dragop)
    {
      dragop = 2;
      int sela = (selStart < caret ? selStart : caret);
      int selb = (selStart > caret ? selStart : caret);
      if (dropPos < sela || dropPos > selb)
      {
        WideString text = getSelection();
        if (lParam != DROPEFFECT_COPY)
        {
          replace(sela, selb, L"");
          if (dropPos > selb)
            dropPos -= (selb - sela);
          caret = replace(dropPos, dropPos, text, NULL, true);
        }
        else
          caret = replace(dropPos, dropPos, text);
        selStart = dropPos;
      }
    }
    else
    {
      caret = replace(dropPos, dropPos, GetGlobalTextWide((HGLOBAL) wParam));
      selStart = dropPos;
      return DROPEFFECT_COPY;
    }
    return lParam;
  case WM_SYSKEYDOWN:
  case WM_KEYDOWN:
    onKey(wParam);
    return 0;
  case WM_COMMAND:
    switch (LOWORD(wParam))
    {
    case ID_EDIT_UNDO:
      {
        bool glue = true;
        bool first = true;
        while (glue && historyPos > 0)
        {
          HistoryItem& h = history[--historyPos];
          replace(h.begin, h.end, h.text, &h);
          glue = h.glue;
          h.glue = !first;
          first = false;
        }
      }
      break;
    case ID_EDIT_REDO:
      {
        bool glue = true;
        bool first = true;
        while (glue && historyPos < history.length())
        {
          HistoryItem& h = history[historyPos++];
          replace(h.begin, h.end, h.text, &h);
          glue = h.glue;
          h.glue = !first;
          first = false;
        }
      }
      break;
    case ID_EDIT_SELECTALL:
      selStart = 0;
      caret = getTextLength();
      updateCaret();
      break;
    case ID_EDIT_COPY:
      if (caret != selStart)
        SetClipboard(CF_UNICODETEXT, CreateGlobalText(getSelection()));
      else
      {
        POINT pt = toPoint(caret);
        pt.x = 0;
        int start = fromPoint(pt);
        if (pt.y < lines.length() - 1)
          pt.y++;
        else
          pt.x = lines[pt.y].text.length();
        int end = fromPoint(pt);
        if (pCopyLine)
          pCopyLine->Release();
        pCopyLine = SetClipboard(CF_UNICODETEXT, CreateGlobalText(substring(start, end)));
        if (pCopyLine)
          pCopyLine->AddRef();
      }
      break;
    case ID_EDIT_CUT:
      if (caret != selStart)
      {
        SetClipboard(CF_UNICODETEXT, CreateGlobalText(getSelection()));
        replace(selStart, caret, L"");
      }
      else
      {
        POINT pt = toPoint(caret);
        POINT save = pt;
        pt.x = 0;
        int start = fromPoint(pt);
        if (pt.y < lines.length() - 1)
          pt.y++;
        else
          pt.x = lines[pt.y].text.length();
        int end = fromPoint(pt);
        if (pCopyLine)
          pCopyLine->Release();
        pCopyLine = SetClipboard(CF_UNICODETEXT, CreateGlobalText(substring(start, end)));
        if (pCopyLine)
          pCopyLine->AddRef();
        replace(start, end, L"");
        caret = selStart = fromPoint(save);
        updateCaret();
      }
      break;
    case ID_EDIT_PASTE:
      {
        ClipboardReader reader(CF_UNICODETEXT);
        if (reader.getData())
        {
          if (OleIsCurrentClipboard(pCopyLine) == S_OK)
          {
            POINT pt = toPoint(caret);
            pt.x = 0;
            caret = selStart = fromPoint(pt);
          }
          selStart = caret = replace(selStart, caret, GetGlobalTextWide(reader.getData()));
          updateCaret();
        }
      }
      break;
    case ID_DEBUG_BREAKPOINT:
      {
        POINT pt = toPoint(caret);
        toggleBreakpoint(pt.y);
      }
      break;
    default:
      return M_UNHANDLED;
    }
    return 0;
  }
  return M_UNHANDLED;
}
Exemplo n.º 24
0
uint32 HeroChart::onMessage(uint32 message, uint32 wParam, uint32 lParam)
{
    switch (message)
    {
    case WM_ERASEBKGND:
    {
        HDC hDC = (HDC) wParam;
        SetBkColor(hDC, 0x000000);
        RECT rc;
        GetClientRect(hWnd, &rc);
        ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
    }
    return TRUE;
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hDC = BeginPaint(hWnd, &ps);

        HDC hBitmapDC = CreateCompatibleDC(hDC);

        SetBkColor(hDC, 0x000000);
        SetBkMode(hDC, OPAQUE);
        for (int i = 0; i < numTags; i++)
        {
            SelectObject(hDC, textTags[i].hFont);
            SetTextColor(hDC, textTags[i].color);
            RECT rc = textTags[i].rc;
            rc.top -= scrollPos;
            rc.bottom -= scrollPos;
            DrawText(hDC, textTags[i].text, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        }

        ImageLibrary* ilib = getApp()->getImageLibrary();
        SelectObject(hDC, counterFont);
        SetTextColor(hDC, 0xFFFFFF);
        for (int i = 0; i < numTaverns; i++)
        {
            if (i == curTavern)
            {
                RECT rc = taverns[i].rc;
                rc.top -= scrollPos + 3;
                rc.bottom -= scrollPos - 3;
                rc.left -= 3;
                rc.right += 3;
                SetBkColor(hDC, taverns[i].color);
                ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
                SetBkColor(hDC, 0x000000);
                rc = taverns[i].rc;
                rc.top -= scrollPos;
                rc.bottom -= scrollPos;
                ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
            }
            for (int h = 0; h < 12; h++)
            {
                Dota::Hero* hero = taverns[i].heroes[h];
                if (hero)
                {
                    int x = taverns[i].rc.left + (32 + 2) * (h % 4);
                    int y = taverns[i].rc.top + (32 + 2) * (h / 4);
                    HBITMAP hBitmap = ilib->getBitmap(String::format("big%s", hero->icon));
                    if (hBitmap)
                    {
                        SelectObject(hBitmapDC, hBitmap);
                        BitBlt(hDC, x, y - scrollPos, 32, 32, hBitmapDC, 0, 0, SRCCOPY);
                        RECT tipRc = {x, y - scrollPos, x + 32, y + 32 - scrollPos};
                        DrawText(hDC, String::format(" %d ", heroCounter[hero->point]),
                                 -1, &tipRc, DT_SINGLELINE | DT_RIGHT | DT_BOTTOM);
                    }
                }
            }
        }

        DeleteDC(hBitmapDC);

        EndPaint(hWnd, &ps);
    }
    break;
    case WM_SIZE:
    {
        SCROLLINFO si;
        memset(&si, 0, sizeof si);
        si.cbSize = sizeof si;
        si.fMask = SIF_PAGE | SIF_RANGE | SIF_DISABLENOSCROLL;
        si.nPage = height();
        si.nMin = 0;
        si.nMax = contentHeight;
        SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
    }
    break;
    case WM_LBUTTONDOWN:
    {
        SetFocus(hWnd);
        int x = GET_X_LPARAM(lParam);
        int y = GET_Y_LPARAM(lParam) + scrollPos;
        for (int i = 0; i < numTaverns; i++)
        {
            if (x >= taverns[i].rc.left && y >= taverns[i].rc.top &&
                    x < taverns[i].rc.right && y < taverns[i].rc.bottom)
            {
                if (curTavern >= 0)
                {
                    RECT rc = taverns[curTavern].rc;
                    rc.left -= 3;
                    rc.top -= scrollPos + 3;
                    rc.right += 3;
                    rc.bottom -= scrollPos - 3;
                    curTavern = i;
                    InvalidateRect(hWnd, &rc, TRUE);
                }
                curTavern = i;
                RECT rc = taverns[i].rc;
                rc.left -= 3;
                rc.top -= scrollPos + 3;
                rc.right += 3;
                rc.bottom -= scrollPos - 3;
                InvalidateRect(hWnd, &rc, TRUE);

                notify(WM_SETTAVERN, i, 0);

                int hx = (x - taverns[i].rc.left) / (32 + 2);
                int hy = (y - taverns[i].rc.top) / (32 + 2);
                int h = hx + hy * 4;
                if (h >= 0 && h < 12 && taverns[i].heroes[h])
                    notify(WM_SETHERO, taverns[i].heroes[h]->point, 0);

                break;
            }
        }
    }
    return 0;
    case WM_MOUSEWHEEL:
        doScroll(scrollPos - GET_WHEEL_DELTA_WPARAM(wParam) * 30 / WHEEL_DELTA);
        break;
    case WM_VSCROLL:
    {
        SCROLLINFO si;
        memset(&si, 0, sizeof si);
        si.cbSize = sizeof si;
        si.fMask = SIF_ALL;
        GetScrollInfo(hWnd, SB_VERT, &si);
        switch (LOWORD(wParam))
        {
        case SB_TOP:
            si.nPos = si.nMin;
            break;
        case SB_BOTTOM:
            si.nPos = si.nMax;
            break;
        case SB_LINEUP:
            si.nPos--;
            break;
        case SB_LINEDOWN:
            si.nPos++;
            break;
        case SB_PAGEUP:
            si.nPos -= si.nPage;
            break;
        case SB_PAGEDOWN:
            si.nPos += si.nPage;
            break;
        case SB_THUMBTRACK:
            si.nPos = si.nTrackPos;
            break;
        }
        doScroll(si.nPos);
    }
    break;
    default:
        return M_UNHANDLED;
    }
    return 0;
}