Mercurial > ~dholland > hg > ag > index.cgi
diff anagram/vaclgui/agview.cpp @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/anagram/vaclgui/agview.cpp Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,1952 @@ +/* + * AnaGram, A System for Syntax Directed Programming + * Copyright 1997-2002 Parsifal Software. All Rights Reserved. + * See the file COPYING for license and usage terms. + * + * agview.cpp + */ + +#include <icoordsy.hpp> +#include <windows.h> + +#include "agstring.h" +#include "agview.hpp" +#include "arrays.h" +#include "config.h" +#include "ctrlpanel.hpp" +#include "dspar.hpp" +#include "frame.hpp" +#include "minmax.h" +#include "vaclgui.hpp" + +//#define INCLUDE_LOGGING +#include "log.h" + + +int focusWindowId; + +const int AgView::defaultWindowHeight = 12; + + +Boolean AgFocusHandler::dispatchHandlerEvent(IEvent &event) { + //LOGSECTION("AgFocusHandler::dispatchHandlerEvent", Log::off); + LOGSECTION_OFF("AgFocusHandler::dispatchHandlerEvent"); + static int focusHandlerCalls = 0; + focusHandlerCalls++; + LOGV(event.eventId()); + if (event.eventId() == WM_SETFOCUS) { + LOGS("WM_SETFOCUS") LCV((int) event.controlWindow()); + int flag; + flag = gotFocus(event); + if (flag) { + event.setResult(flag); + } + return flag; + } + if (event.eventId() == WM_KILLFOCUS) { + LOGS("WM_KILLFOCUS") LCV((int) event.controlWindow()); + int flag = lostFocus(event); + event.setResult(flag); + return flag; + } + return false; +} + +AgColumnHead::AgColumnHead(int id, IWindow* parent) + : IStaticText(id, parent, parent) + , title() + , nCols(0) + , tabs(0) + , xPos(0) + , color(&ColorSpec::inactiveTitle) + , dataColorChange(this, onColorChange) +{ + LOGSECTION("AgColumnHead constructor"); + IPaintHandler::handleEventsFor(this); +/* + yBias = + ICoordinateSystem::isConversionNeeded() + ? font().maxSize().height() - font().maxDescender() + : 0; + LOGV(yBias); +*/ + dataColorChange.attach(&ColorSpec::data); + dataColorChange.attach(&ColorSpec::inactiveTitle); + dataColorChange.attach(&ColorSpec::activeTitle); + setText("Column headers"); + show(); +} + + +AgColumnHead::~AgColumnHead() { + IPaintHandler::stopHandlingEventsFor(this); +} + +void AgColumnHead::setTitles(int nCols_, AgString title_) { + LOGSECTION("AgColumnHead::setTitles"); + nCols = nCols_; + title = title_; + + setText(title.pointer()); + LOGV(title.pointer()); + LOGV(size().asString()); +} + +void AgColumnHead::setMargin(int margin_) { + margin = margin_; +} + +void AgColumnHead::setPos(int pos_) { + xPos = pos_; +} + +void AgColumnHead::setTabs(int *tabs_) { + tabs = tabs_; +} + +Boolean AgColumnHead::paintWindow(IPaintEvent &event) { + int i = 0; + + if (event.rect().area() == 0) { + return true; + } + LOGSECTION("AgColumnHead::paintWindow"); + LOGV(title.pointer()); + IPresSpaceHandle handle = event.presSpaceHandle(); //cookie + SetBkMode(handle, TRANSPARENT); + event.clearBackground(color->bg()); + font().beginUsingFont(handle); + int textHeight = font().maxSize().height(); + int verticalMargin = (size().height() - textHeight)/2; + + LOGV(textHeight); + LOGV(verticalMargin); + //LOGV(yBias); + LOGV(margin); + LOGV(xPos); + int yBias = + ICoordinateSystem::isConversionNeeded() + ? font().maxSize().height() - font().maxDescender() + : 0; + IPoint trueWhere(margin - xPos, verticalMargin + yBias); + IPoint where = + ICoordinateSystem::isConversionNeeded() + ? ICoordinateSystem::convertToNative(trueWhere, size()) + : trueWhere; + + LOGV(trueWhere.asString()); + LOGV(where.asString()); + AgString temp(title.pointer()); + FindTabs tabsKluge(temp.pointer()); + char *p = tabsKluge.getField(); + LOGV(rect().asString()); + while (i < nCols) { + LOGV(i); + LOGV(p); + LOGV(where.asString()); + LOGV(color->fg().asString()); + LOGV(p) LCV(where.asString()); + event.drawText(p,where, color->fg()); + where += IPoint(tabs[i], 0); + p = tabsKluge.getField(); + i++; + } + font().endUsingFont(handle); + return true; +} + +AgStaticText &AgStaticText::scrollWindow(IPoint distance) { + IRectangle clipRect(size()); + + //LOGSECTION("AgStaticText::scrollWindow", Log::off); + LOGSECTION_OFF("AgStaticText::scrollWindow"); + LOGV(distance.asString()); + LOGV(clipRect.asString()); + + RECTL rct = clipRect.asRECTL(); + ScrollWindowEx(handle(), distance.x(), distance.y(), 0, (RECT *) &rct, + 0,0,SW_INVALIDATE); + return *this; +} + +AgView &AgView::hideCursor() { + if (!cursorEnabled) { + return *this; + } + //LOGSECTION("AgView::hideCursor", Log::off); + LOGSECTION_OFF("AgView::hideCursor"); + cursorHideCount++; + LOGV(cursorHideCount); + IFLOG(int flag = ) HideCaret(dataArea.handle()); + LOGV(flag); + return *this; +} + +AgView &AgView::showCursor() { + if (!cursorEnabled) { + return *this; + } + //LOGSECTION("AgView::showCursor", Log::off); + LOGSECTION_OFF("AgView::showCursor"); + cursorHideCount--; + LOGV(cursorHideCount); + IFLOG(int flag = ) ShowCaret(dataArea.handle()); + LOGV(flag); + return *this; +} + + + +AgView::AgView(IWindow *ownerWindow_) + : ICanvas(nextChildId(), ownerWindow_, ownerWindow_) + , ownerWindow(ownerWindow_) + , horizontalScrollBar(nextChildId(), this, this, IRectangle(), + IScrollBar::horizontal + | IWindow::visible) + , verticalScrollBar(nextChildId(), this, this, IRectangle(), + IScrollBar::vertical + | IWindow::visible) + , dataHole(nextChildId(), this, this) + , dataArea(nextChildId(), &dataHole, &dataHole) + , vsbShowing(false) + , hsbShowing(false) + , columnHeadTitle(nextChildId(), this) + , columnHeadsPresent(0) + , cursorLine(0) + , mouseDown(0) + , tabArray(0) + , tableWidth(0) + , tableHeight(0) + , cursorEnabled(0) + , cursorLocation(0,0) + , pixelCursor(font().avgCharWidth(),0) + , cursorLineHighlight(0) + , prevHorizontal(0) + , prevVertical(0) + , color(&ColorSpec::syntaxFile) + , cursorColor(&ColorSpec::activeCursor) + , rightButtonDown(0) + , layoutActive(0) + , retainCursor(cursorLineHighlight) + , frameWindow(0) + , dataColorChange(this, onColorChange) +{ + LOGSECTION("AgView constructor"); + LOGV(id()) LCV((int) this) LCV(handle().asDebugInfo()); + LOGV(dataArea.id()) LCV((int) &dataArea) + LCV(dataArea.handle().asDebugInfo()); + dataColorChange.attach(&ColorSpec::data); + dataColorChange.attach(&ColorSpec::inactiveCursor); + dataColorChange.attach(&ColorSpec::activeCursor); + for (int i = 0; i < 256; i++) { + charWidth[i] = font().charWidth(i); + } + IWindow *f; + for (f = ownerWindow; !f->isFrameWindow(); f=f->parent()); + frameWindow = (AgFrame *) f; + windowId = id(); + AgString title = columnTitleText(); + LOGV(title.pointer()); + if (title.exists()) { + columnHeadTitle.setTitles(nColumns(), title); + ISize size = columnHeadTitle.size(); + columnHeadTitle.setMinimumSize(size); + LOGV(size.asString()); + columnHeadTitle.setMargin(avgCharWidth()); + columnHeadTitle.enableFillBackground(); + columnHeadsPresent = 1; + } + + horizontalScrollBar.setScrollableRange(IRange(0, 100)); + horizontalScrollBar.moveScrollBoxTo(0); + verticalScrollBar.setScrollableRange(IRange(0, 100)); + verticalScrollBar.moveScrollBoxTo(0); + + IKeyboardHandler::handleEventsFor(&dataArea); + IMouseHandler ::handleEventsFor(&dataArea); + IMouseHandler ::handleEventsFor(&columnHeadTitle); + IMouseHandler ::handleEventsFor(&verticalScrollBar); + IMouseHandler ::handleEventsFor(&horizontalScrollBar); + IPaintHandler ::handleEventsFor(&dataArea); + IResizeHandler ::handleEventsFor(this); + IScrollHandler ::handleEventsFor(this); + show(); +} + +AgView::~AgView() { + delete [] tabArray; + if (cursorEnabled) { + AgFocusHandler::stopHandlingEventsFor(this); + AgFocusHandler::stopHandlingEventsFor(&dataArea); + } + IKeyboardHandler::stopHandlingEventsFor(&dataArea); + IMouseHandler ::stopHandlingEventsFor(&dataArea); + IMouseHandler ::stopHandlingEventsFor(&columnHeadTitle); + IMouseHandler ::stopHandlingEventsFor(&verticalScrollBar); + IMouseHandler ::stopHandlingEventsFor(&horizontalScrollBar); + IPaintHandler ::stopHandlingEventsFor(&dataArea); + IResizeHandler ::stopHandlingEventsFor(this); + IScrollHandler ::stopHandlingEventsFor(this); +} + +AgView &AgView::enableCursorBar(int flag) { + flag = (flag != 0); + if (flag == cursorLineHighlight) { + return *this; + } + cursorLineHighlight = flag; + if (flag) { + retainCursor = 1; + AgFocusHandler::handleEventsFor(&dataArea); + AgFocusHandler::handleEventsFor(this); + LOGV(dataArea.hasFocus()); + LOGV(hasFocus()); + if (dataArea.hasFocus()) { + LOGV(dataArea.size().height()); + cursorOn(); + //setCursorPos(pixelCursor); + } + } + else { + if (dataArea.hasFocus()) { + //hideCursor(); + cursorOff(); + } + AgFocusHandler::stopHandlingEventsFor(&dataArea); + AgFocusHandler::stopHandlingEventsFor(this); + } + return *this; +} + +AgView &AgView::enableCursor(int flag) { + LOGSECTION("AgView::enableCursor"); + LOGV(cursorEnabled) LCV(flag); + flag = (flag != 0); + if (flag == cursorEnabled) { + return *this; + } + LOGS("changing cursor state"); + cursorEnabled = flag; + LOGV(cursorEnabled); + if (flag) { + retainCursor = 0; + AgFocusHandler::handleEventsFor(&dataArea); + AgFocusHandler::handleEventsFor(this); + LOGV(dataArea.hasFocus()); + LOGV(hasFocus()); + if (dataArea.hasFocus()) { + LOGV(dataArea.size().height()); + cursorOn(); + //setCursorPos(pixelCursor); + } + } + else { + if (dataArea.hasFocus()) { + //hideCursor(); + cursorOff(); + } + AgFocusHandler::stopHandlingEventsFor(&dataArea); + AgFocusHandler::stopHandlingEventsFor(this); + } + return *this; +} + +AgView &AgView::cursorOn() { + //LOGSECTION("AgView::cursorOn", Log::off); + LOGSECTION_OFF("AgView::cursorOn"); + cint origin(horizontalScrollBar.scrollBoxPosition(), + lineHeight()*verticalScrollBar.scrollBoxPosition()); + pixelCursor.y = lineHeight()*cursorLine; + pixelCursor.x = xPosition(cursorLocation.x, getLine(cursorLine)); + cint relativeCursor = pixelCursor - origin; + LOGV(relativeCursor); + LOGV(cursorLine); + LOGV(pixelCursor); + LOGV(dataArea.rect().asString()); + LOGV(dataArea.hasFocus()); + IFLOG(int flag = ) CreateCaret(dataArea.handle(), NULL,0, lineHeight()); + LOGV(flag); + SetCaretPos(relativeCursor.x, relativeCursor.y); + IFLOG(flag = ) ShowCaret(dataArea.handle()); + LOGV(flag); + cursorHideCount = 0; + return *this; +} + +AgView &AgView::setCursorPos(cint cursor) { + if (!cursorEnabled) { + return *this; + } + //LOGSECTION("AgView::setCursorPos", Log::off); + LOGSECTION("AgView::setCursorPos"); + LOGSTACK; + cint origin(horizontalScrollBar.scrollBoxPosition(), + lineHeight()*verticalScrollBar.scrollBoxPosition()); + + //cint origin(0, lineHeight()*verticalScrollBar.scrollBoxPosition()); + cint relativeCursor = cursor - origin; + LOGV(cursor) LCV(origin) LCV(relativeCursor); + hideCursor(); + IFLOG(int flag = ) SetCaretPos(relativeCursor.x, relativeCursor.y); + LOGV(flag); + showCursor(); + return *this; +} + +AgView &AgView::cursorOff() { + //LOGSECTION("AgView::cursorOff", Log::off); + LOGSECTION_OFF("AgView::cursorOff"); + IFLOG(int flag = ) DestroyCaret(); + LOGV(flag); + return *this; +} + +Boolean AgView::gotFocus(IEvent &) { + //LOGSECTION("AgView::gotFocus", Log::off); + LOGSECTION_OFF("AgView::gotFocus"); + //LOGSTACK; + if (cursorEnabled) { + LOGV(pixelCursor); + LOGV(dataArea.size().height()); + cursorOn(); + //setCursorPos(pixelCursor); + } + columnHeadTitle.color = &ColorSpec::activeTitle; + columnHeadTitle.refresh(); + if (cursorLineHighlight) { + cursorColor = &ColorSpec::activeCursor; + repaintLine(cursorLine); + } + focusWindowId = windowId; + return false; + //return true; +} + +Boolean AgView::lostFocus(IEvent &) { + //LOGSECTION("AgView::lostFocus", Log::off); + LOGSECTION_OFF("AgView::lostFocus"); + //LOGSTACK; + if (cursorEnabled) { + //hideCursor(); + cursorOff(); + } + columnHeadTitle.color = &ColorSpec::inactiveTitle; + columnHeadTitle.refresh(); + if (cursorLineHighlight) { + cursorColor = &ColorSpec::inactiveCursor; + repaintLine(cursorLine); + } + return false; +} + +int AgView::findMaxWidth() { + LOGSECTION("AgView::findMaxWidth"); + int maxWidth = 0; + int nl = nLines(); + int nCols = nColumns(); + LOGV(nl) LCV(nCols); + char *columnTitles = columnTitleText().pointer(); + int i; + + if (tabArray == NULL) { + tabArray = new int[nCols + 1]; + memset(tabArray, 0, (nCols+1)*sizeof(int)); + } + IFont windowFont = font(); + + if (columnTitles) { + //char *titles = new char[1+strlen(columnTitles)]; + //char *titles = local_array(1+strlen(columnTitles), char); + LocalArray<char> titles(1+strlen(columnTitles)); + strcpy(titles, columnTitles); + FindTabs tabs(titles); + char *p = tabs.getField(); + i = 0; + while(i < nCols && p) { + int width = windowFont.textWidth(p); + if (width > tabArray[i]) { + tabArray[i] = width; + } + if (++i >= nCols) { + break; + } + p = tabs.getField(); + } + while (i < nCols) { + tabArray[i++] = 0; + } + //delete [] titles; + } + else { + for (i = 0; i < nCols; i++) { + tabArray[i] = 0; + } + } + columnHeadWidth = 0; + for (i = 0; i < nCols; i++) { + columnHeadWidth += tabArray[i] + 2*avgCharWidth(); + } + //int *width = new int[nCols]; + //int *width = local_array(nCols, int); + int *width = LocalArray<int>(nCols); + memset(width, 0, nCols*sizeof(int)); + LOGV((int) width); + LOGV((int) tabArray); + int enWidth = avgCharWidth(); + int columnWidth = enWidth*tab_spacing; + while (nl--) { + LOGV(nl); + AgString line = getLine(nl); + LOGV(line); + LOGV(nl); + FindTabs tabs(line.pointer()); + char *p = tabs.getField(); + LOGV(nl) LCV((int) p); + LOGV(p); + int whereX = 0; + if (nCols > 1) { + i = 0; + while (i < nCols && p) { + width[i] = windowFont.textWidth(p); + LOGV(width[i]); + if (++i >= nCols) { + break; + } + p = tabs.getField(); + } + if (i < nCols) { + continue; + } + } + else { + while (p) { + width[0] = whereX + font().textWidth(p); + whereX = ((width[0] + columnWidth)/columnWidth) * columnWidth; + p = tabs.getField(); + } + } + for (i = 0; i < nCols; i++) { + if (width[i] > tabArray[i]) { + tabArray[i] = width[i]; + LOGS("***") LV(tabArray[i]); + } + LOGS("***") LV(tabArray[i]); + } + } + LOGS("width measured"); + //delete [] width; + for (i = 0; i < nCols; i++) { + tabArray[i] += 2*avgCharWidth(); + maxWidth += tabArray[i]; + } + LOGV(maxWidth); + return maxWidth; +} + +ICanvas &AgView::layout() { + LOGSECTION("AgView::layout"); + if (layoutActive) { + return *this; + } + layoutActive++; + doLayout(); + ICanvas::setLayoutDistorted(0, IWindow::layoutChanged); + ICanvas::layout(); + layoutActive--; + return *this; +} + +ICanvas &AgView::setLayoutDistorted(unsigned long i, unsigned long j) { + //LOGSECTION("AgView::setLayoutDistorted", Log::off); + LOGSECTION_OFF("AgView::setLayoutDistorted"); + //i &= ~IWindow::fontChanged; + //j |= IWindow::fontChanged; + tableWidth = 0; + ICanvas::setLayoutDistorted(i, j); + return *this; +} + +Boolean AgView::windowResize(IResizeEvent &){ + LOGSECTION("AgView resize event"); + setLayoutDistorted(IWindow::layoutChanged,0); + return false; +} + +ISize AgView::suggestSize() { + LOGSECTION("AgView::suggestSize"); + int width = findMaxWidth(); + int minWidth = 40*font().avgCharWidth(); + int maxWidth = 60*font().avgCharWidth(); + if (width < minWidth) { + width = minWidth; + } + if (width > maxWidth) { + width = maxWidth; + } + int height = tableHeight; + if (nLines() > defaultWindowHeight) { + width += verticalScrollBar.minimumSize().width() + 1; + height = lineHeight() * defaultWindowHeight; + } + else if (nLines() < 5) { + height = lineHeight() * 5; + } + LOGV(width); + LOGV(height); + return ISize(width, height); +} + +Boolean AgView::paintWindow(IPaintEvent &event) { + if (event.controlWindow() != &dataArea) { + return false; + } + + int height = lineHeight(); + LOGSECTION("AgView::paintWindow"); + + IPresSpaceHandle handle = event.presSpaceHandle(); //cookie + SetBkMode(handle, TRANSPARENT); + + font().beginUsingFont(handle); + LOGV(event.rect().asString()); + IRectangle invalidRect( + ICoordinateSystem::isConversionNeeded() + ? ICoordinateSystem::convertToApplication(event.rect(),dataArea.size()) + : event.rect() + ); + LOGV(invalidRect.asString()); + LOGV(dataHole.rect().asString()); + LOGV(dataArea.rect().asString()); + + int baseLine = verticalScrollBar.scrollBoxPosition(); + int topY = baseLine*lineHeight(); + int minY = topY + invalidRect.minY(); + int maxY = topY + invalidRect.maxY(); + int bottomY = topY + dataHole.size().height(); + LOGV(minY) LCV(maxY); + LOGV(topY) LCV(bottomY); + if (minY < topY) { + minY = topY; + } + if (maxY > bottomY) { + maxY = bottomY; + } + invalidRect = IRectangle(IPoint(invalidRect.minX(), minY), + (IPoint(invalidRect.maxX(), maxY))); + + LOGV(invalidRect.asString()); + LOGV(dataHole.size().asString()); + int firstLine = invalidRect.minY()/height; + int lastLine = (invalidRect.maxY()+height - 1)/height - 1; + + if (firstLine < baseLine) { + firstLine = baseLine; + lastLine += baseLine; + } + + int yBias = + ICoordinateSystem::isConversionNeeded() + ? height - maxDescender() + : 0; + + + int xMargin = avgCharWidth(); + + int whereX = -horizontalScrollBar.scrollBoxPosition(); + int whereY = firstLine*height - topY; //baseline location + + IColor textBgndColor=color->bg(); + IColor textFgndColor=color->fg(); + IColor cursorBgndColor=color->bg(); + IColor cursorFgndColor=color->fg(); + if (cursorLineHighlight) { + cursorBgndColor=cursorColor->bg(); + cursorFgndColor=cursorColor->fg(); + } + + LOGV(baseLine); + LOGV(firstLine); + LOGV(lastLine); + LOGV(horizontalScrollBar.scrollBoxPosition()); + + int lastInvalidLine = lastLine; + if (lastLine >= nLines()) { + lastLine = nLines() - 1; + } + int windowHeight = dataArea.rect().size().height(); + int dataAreaWidth = dataArea.rect().size().width() - whereX; + ISize lineSize(dataAreaWidth, height); + IPoint offset(xMargin, 0); + int k; + + for (k = firstLine; k <= lastLine; k++, whereY += height) { + //LOGSECTION("AgDataView::paintWindow line loop", Log::off); + LOGSECTION_OFF("AgDataView::paintWindow line loop"); + IPoint trueWhere(whereX, whereY + yBias); + IPoint where = + ICoordinateSystem::isConversionNeeded() + ? ICoordinateSystem::convertToNative(trueWhere, dataArea.size()) + : trueWhere; + IRectangle trueLineRect(0, whereY, dataAreaWidth, whereY+height); + IRectangle lineRect = + ICoordinateSystem::isConversionNeeded() + ? ICoordinateSystem::convertToNative(trueLineRect, dataArea.size()) + : trueLineRect; + IColor bgndColor = textBgndColor; + IColor fgndColor = textFgndColor; + if (k == cursorLine) { + bgndColor = cursorBgndColor; + fgndColor = cursorFgndColor; + } + LOGV(lineRect.asString()); + LOGV(where.asString()); + event.clearBackground(lineRect,bgndColor); + AgString line = getLine(k); + LOGV(line.pointer()); + FindTabs tabs(line.pointer()); + int enWidth = avgCharWidth(); + int columnWidth = enWidth*tab_spacing; + char *p = tabs.getField(); + int nCols = nColumns(); + where += offset; + int i = 0; + if (nCols > 1) { + while (i < nCols && p) { + LOGV(p - line.pointer()); + event.drawText(p, where, fgndColor); + where += IPoint(tabArray[i], 0); + if (++i >= nCols) { + break; + } + p = tabs.getField(); + } + } + else { + while (p) { + event.drawText(p, where, fgndColor); + int whereX = where.x(); + whereX += font().textWidth(p); + whereX += horizontalScrollBar.scrollBoxPosition() - enWidth; + whereX = ((whereX + columnWidth)/columnWidth) * columnWidth; + whereX -= horizontalScrollBar.scrollBoxPosition() - enWidth; + where.setX(whereX); + p = tabs.getField(); + } + } + } + if (k <= lastInvalidLine) { + IRectangle trueRemainder(0,whereY,dataAreaWidth, windowHeight); + IRectangle remainder = + ICoordinateSystem::isConversionNeeded() + ? ICoordinateSystem::convertToNative(trueRemainder, dataArea.size()) + : trueRemainder; + LOGV(remainder.asString()); + event.clearBackground(remainder,textBgndColor); + } + font().endUsingFont(handle); + return true; +} + +AgView &AgView::repaintLine(int line) { + LOGSECTION("AgView::repaintLine"); + if (line < 0 || line >= nLines()) { + return *this; + } + int baseLine = verticalScrollBar.scrollBoxPosition(); + int y = (line - baseLine) * lineHeight(); + IRectangle rect(0, y, dataArea.rect().size().width(), y + lineHeight()); + LOGV(line) LCV(baseLine) LCV(y) LCV(rect.asString()); + dataArea.refresh(rect); + return *this; +} + +AgView &AgView::updateCursor(int line) { + LOGSECTION_OFF("AgView::updateCursor"); + LOGV(line) LCV(cursorLine); + if (retainCursor && line != cursorLine) { + int oldCursor = cursorLine; + if (cursorLine < line) { + cursorLocation.y = cursorLine = line; + } + int bottomLine = line + verticalScrollBar.visibleCount() - 1; + if (cursorLine > bottomLine) { + cursorLocation.y = cursorLine = bottomLine; + } + LOGV(line) LCV(cursorLine) LCV(bottomLine); + if (cursorLineHighlight && cursorLine != oldCursor) { + repaintLine(oldCursor); + repaintLine(cursorLine); + } + } + reposition(); + cursorLocation.y = cursorLine; + pixelCursor.y = lineHeight() * cursorLine; + if (cursorEnabled && dataArea.hasFocus()) { + setCursorPos(pixelCursor); + } + return *this; +} + +AgView &AgView::reposition() { + //LOGSECTION("AgView::reposition", Log::off); + LOGSECTION("AgView::reposition"); + + if (cursorEnabled) hideCursor(); + int verticalOffset = verticalScrollBar.scrollBoxPosition() + - prevVertical; + + int horizontalOffset = horizontalScrollBar.scrollBoxPosition() + - prevHorizontal; + + IPoint displacement(-horizontalOffset, -lineHeight()*verticalOffset); + + LOGV(displacement.asString()); + + dataArea.scrollWindow(displacement); + dataArea.refresh(); + prevHorizontal = horizontalScrollBar.scrollBoxPosition(); + prevVertical = verticalScrollBar.scrollBoxPosition(); + cursorLocation.y = cursorLine; + pixelCursor.y = cursorLine*lineHeight(); + if (cursorEnabled) { + setCursorPos(pixelCursor).showCursor(); + } + return *this; +} + +AgView &AgView::repaintCursor(int line) { + LOGSECTION("AgView::repaintCursor"); + LOGV(line) LCV(cursorLine); + cursorLocation.y = cursorLine; + pixelCursor.y = cursorLine*lineHeight(); + if (cursorLineHighlight && cursorLine != line) { + repaintLine(line); + repaintLine(cursorLine); + } + return *this; +} + +AgView &AgView::updateCursor() { + LOGSECTION("AgView::updateCursor"); + cursorLocation.y = cursorLine; + LOGV(cursorLocation); + pixelCursor.y = cursorLine*lineHeight(); + LOGV(pixelCursor); + if (cursorEnabled) { + setCursorPos(pixelCursor); + } + return *this; +} + +/* + * + * Layout considerations: + * + * The data view consists of up to four parts: two scroll bars, a heading + * and a data area. + * + * The presence or absence of the scroll bars depends on the relative size + * of the data area and the size of the table to be displayed. + */ + +AgView &AgView::doLayout() { + LOGSECTION("AgView::doLayout"); + if (cursorEnabled && dataArea.hasFocus()) { + hideCursor(); + } + + if (tableWidth == 0) { + tableWidth = findMaxWidth(); + } + tableHeight = lineHeight()*nLines(); + + LOGV(tableWidth); + LOGV(tableHeight); + columnHeadTitle.setTabs(tabArray); + ISize canvasSize = size(); + int canvasWidth = canvasSize.width(); + int canvasHeight = canvasSize.height(); + if (canvasWidth == 0 && canvasHeight == 0) { + return *this; + } + + LOGV(canvasWidth); + LOGV(canvasHeight); + + int dataWidth = canvasWidth; + int dataHeight = canvasHeight; + int dataY = 0; + if (columnHeadsPresent) { + dataY = columnHeadTitle.minimumSize().height(); + dataHeight -= dataY; + columnHeadTitle.moveTo(IPoint(0,0)); + } + + LOGV(dataWidth); + LOGV(dataHeight); + + LOGV(tableWidth); + LOGV(tableHeight); + + + int vsbWidth = verticalScrollBar.minimumSize().width(); + int hsbHeight = horizontalScrollBar.minimumSize().height(); + + int horizontalPosition = horizontalScrollBar.scrollBoxPosition(); + int verticalPosition = verticalScrollBar.scrollBoxPosition(); + + Boolean vsb = true; + Boolean hsb = true; + + if (tableHeight > canvasHeight + && tableWidth <= canvasWidth - vsbWidth - 1) { + // vertical scroll bar only + vsb = true; + hsb = false; + } + else if (tableWidth > canvasWidth + && tableHeight <= canvasHeight - hsbHeight - 1) { + // horizontal scroll bar only + vsb = false; + hsb = true; + } + else if (tableWidth <= canvasWidth && tableHeight <= canvasHeight) { + // no scroll bars + vsb = hsb = false; + } + LOGV(vsb) LCV(vsbShowing); + LOGV(hsb) LCV(hsbShowing); + + if (vsb && !vsbShowing) { + verticalScrollBar.moveScrollBoxTo(0); + prevVertical = 0; + verticalScrollBar.show(); + vsbShowing = true; + } + if (!vsb && vsbShowing) { + verticalScrollBar.hide(); + vsbShowing = false; + verticalScrollBar.moveScrollBoxTo(0); + prevVertical = 0; + } + + if (hsb && !hsbShowing) { + horizontalScrollBar.show(); + hsbShowing = true; + horizontalScrollBar.moveScrollBoxTo(0); + prevHorizontal = 0; + } + if (!hsb && hsbShowing) { + horizontalScrollBar.hide(); + hsbShowing = false; + horizontalScrollBar.moveScrollBoxTo(0); + prevHorizontal = 0; + } + + if (vsbShowing) { + dataWidth -= vsbWidth + 1; + verticalScrollBar.moveTo(IPoint(dataWidth+1, 0)); + verticalScrollBar.sizeTo(ISize(vsbWidth, canvasHeight)); + } + + if (hsbShowing) { + dataHeight -= hsbHeight + 1; + horizontalScrollBar.moveTo(IPoint(0, dataHeight+1)); + horizontalScrollBar.sizeTo(ISize(dataWidth, hsbHeight)); + } + + dataHole.sizeTo(ISize(dataWidth, dataHeight)); + dataHole.moveTo(IPoint(0, dataY)); + + LOGV(nLines()); + LOGV(lineHeight()); + LOGV(nLines()*lineHeight()); + + int desiredWidth = tableWidth; + if (tableWidth < dataWidth) { + desiredWidth = dataWidth; + } + ISize desiredSize(desiredWidth, dataHeight); + + LOGV(desiredSize.asString()); + + dataArea.sizeTo(desiredSize); + + LOGV(dataArea.size().asString()); + LOGV(dataArea.parentSize().asString()); + + dataArea.moveTo(IPoint(0, 0)); + LOGV(rect().asString()); + LOGV(dataArea.rect().asString()); + LOGV(horizontalScrollBar.rect().asString()); + LOGV(verticalScrollBar.rect().asString()); + + horizontalScrollBar.setScrollableRange(IRange(0,tableWidth-1)); + horizontalScrollBar.setVisibleCount(dataWidth); + + verticalScrollBar.setVisibleCount(dataHeight/lineHeight()); + verticalScrollBar.setScrollableRange(IRange(0, nLines() - 1)); + + horizontalPosition = min( + (int) horizontalScrollBar.scrollBoxRange().upperBound(), + horizontalPosition + ); + verticalPosition = min( + (int) verticalScrollBar.scrollBoxRange().upperBound(), + verticalPosition + ); + + verticalPosition = max( + (int)(cursorLine - verticalScrollBar.visibleCount() + 1), + verticalPosition + ); + + horizontalScrollBar.setMinScrollIncrement(maxCharWidth()); + verticalScrollBar.setMinScrollIncrement(1); + + horizontalScrollBar.moveScrollBoxTo(horizontalPosition); + prevHorizontal = horizontalPosition; + verticalScrollBar.moveScrollBoxTo(verticalPosition); + prevVertical = verticalPosition; + if (columnHeadsPresent) { + ISize headSize(dataWidth, columnHeadTitle.minimumSize().height()); + columnHeadTitle.sizeTo(headSize); + columnHeadTitle.xPos = horizontalPosition; + columnHeadTitle.refresh(); + } + refresh(); + LOGV(dataArea.hasFocus()); + LOGV(vsb) LCV(vsbShowing); + LOGV(hsb) LCV(hsbShowing); + if (cursorEnabled && dataArea.hasFocus()) { + setCursorPos(pixelCursor).showCursor(); + } + return *this; +} + +int AgView::charPosition(int xPos, AgString line) { + int i; + int enWidth = avgCharWidth(); + int x = enWidth; + int columnWidth = enWidth*tab_spacing; + int spaceWidth = charWidth[' ']; + unsigned char *p = (unsigned char *) line.pointer(); + + //LOGSECTION("AgView::charPosition", Log::off); + LOGSECTION_OFF("AgView::charPosition"); + + LOGV(p) LCV(xPos); + + if (p == 0) { + return 0; + } + for (i = 0; p[i]; i++) { + int newX = x + charWidth[p[i]]; + if (p[i] == '\t') { + LOGSECTION("AgView::charPosition::tab"); + LOGV(x) LCV(columnWidth); + int j = 0; + if (nColumns() > 1 && tabArray) { + while (tabArray[j] && tabArray[j] <= x) { + j++; + } + if (tabArray[j] > newX) { + newX = tabArray[j]; + } + } + else { +/* + int hPos = horizontalScrollBar.scrollBoxPosition(); + newX = x + hPos - enWidth; + newX = ((newX + columnWidth)/columnWidth)*columnWidth; + newX -= hPos - enWidth; +*/ + newX = enWidth + ((x-enWidth + columnWidth)/columnWidth) * columnWidth; + } + LOGV(x); + } + if (p[i] == ' ') { + LOGV(x); + newX = x + spaceWidth; + } + //if (newX > xPos) { + if (xPos <= (x+newX)/2) { + LOGV(i) LCV(xPos) LCV(x) LCV(newX); + return i; + } + x = newX; + } + return i ? i - 1 : 0; +} + +int AgView::xPosition(int charPos, AgString line) { + //LOGSECTION("AgView::xPosition", Log::off); + LOGSECTION_OFF("AgView::xPosition"); + int i; + int enWidth = avgCharWidth(); + int x = enWidth; + int columnWidth = enWidth*tab_spacing; + int spaceWidth = charWidth[' ']; + unsigned char *p = (unsigned char *) line.pointer(); + + LOGV(p); + LOGV(charPos); + LOGV(line.pointer()); + + if (p == 0) { + return x; + } + for (i = 0; p[i] && i < charPos; i++) { + if (p[i] == '\t') { + LOGSECTION("AgView::xPosition::tab"); + LOGV(x) LCV(columnWidth); + int j = 0; + if (nColumns() > 1 && tabArray) { + while (tabArray[j] && tabArray[j] <= x) { + j++; + } + if (tabArray[j] > x) { + x = tabArray[j]; + } + } + else { + x = enWidth + ((x-enWidth + columnWidth)/columnWidth) * columnWidth; + } +/* + else { + int hPos = horizontalScrollBar.scrollBoxPosition(); + x += hPos - enWidth; + x = ((x + columnWidth)/columnWidth)*columnWidth; + x -= hPos - enWidth; + } +*/ + LOGV(x); + continue; + } + if (p[i] == ' ') { + LOGV(x); + x += spaceWidth; + continue; + } + x += charWidth[p[i]]; + } + LOGV(x); + LOGV(i); + return x; +} + +void AgView::checkFocus(void) { +#ifdef AG_WINDOWSX + if (!dataArea.hasFocus()) { + dataArea.setFocus(); + } +#endif +} + +Boolean AgView::lineDown(IScrollEvent &event) { + if (event.scrollBarWindow() != &verticalScrollBar) { + return false; + } + //LOGSECTION("AgView::lineDown", Log::off); + LOGSECTION_OFF("AgView::lineDown"); + LOGV(cursorLine); + checkFocus(); + hideCursor(); + moveScrollBox(event); + int line = verticalScrollBar.scrollBoxPosition(); + updateCursor(line); + showCursor(); + return true; +} + +Boolean AgView::lineLeft(IScrollEvent &event) { + if (event.scrollBarWindow() != &horizontalScrollBar) { + return false; + } + //LOGSECTION("AgView::lineLeft", Log::off); + LOGSECTION_OFF("AgView::lineLeft"); + if (cursorEnabled) { + hideCursor(); + } + checkFocus(); + moveScrollBox(event); + reposition(); + if (cursorEnabled) { + setCursorPos(pixelCursor).showCursor(); + } + return true; +} + +Boolean AgView::lineRight(IScrollEvent &event) { + if (event.scrollBarWindow() != &horizontalScrollBar) { + return false; + } + //LOGSECTION("AgView::lineRight", Log::off); + LOGSECTION_OFF("AgView::lineRight"); + checkFocus(); + if (cursorEnabled) { + hideCursor(); + } + moveScrollBox(event); + reposition(); + if (cursorEnabled) { + showCursor(); + } + return true; +} + +Boolean AgView::lineUp(IScrollEvent &event) { + if (event.scrollBarWindow() != &verticalScrollBar) { + return false; + } + checkFocus(); + hideCursor(); + moveScrollBox(event); + int line = verticalScrollBar.scrollBoxPosition(); + updateCursor(line); + showCursor(); + return true; +} + +Boolean AgView::pageDown(IScrollEvent &event) { + if (event.scrollBarWindow() != &verticalScrollBar) { + return false; + } + checkFocus(); + hideCursor(); + moveScrollBox(event); + int line = verticalScrollBar.scrollBoxPosition(); + updateCursor(line); + showCursor(); + return true; +} + +Boolean AgView::pageLeft(IScrollEvent &event) { + if (event.scrollBarWindow() != &horizontalScrollBar) { + return false; + } + checkFocus(); + if (cursorEnabled) { + hideCursor(); + } + moveScrollBox(event); + reposition(); + if (cursorEnabled) { + showCursor(); + } + return true; +} + +Boolean AgView::pageRight(IScrollEvent &event) { + if (event.scrollBarWindow() != &horizontalScrollBar) { + return false; + } + checkFocus(); + if (cursorEnabled) { + hideCursor(); + } + moveScrollBox(event); + reposition(); + if (cursorEnabled) { + showCursor(); + } + return true; +} + +Boolean AgView::pageUp(IScrollEvent &event) { + if (event.scrollBarWindow() != &verticalScrollBar) { + return false; + } + checkFocus(); + hideCursor(); + moveScrollBox(event); + int line = verticalScrollBar.scrollBoxPosition(); + updateCursor(line); + showCursor(); + return true; +} + +Boolean AgView::scrollBoxTrack(IScrollEvent &event) { + checkFocus(); + if (cursorEnabled) { + hideCursor(); + } + moveScrollBox(event); + reposition(); + if (event.scrollBarWindow() == &verticalScrollBar) { + int line = verticalScrollBar.scrollBoxPosition(); + updateCursor(line); + if (cursorEnabled) { + showCursor(); + } + return true; + } + if (cursorEnabled) { + showCursor(); + } + //if (event.scrollBarWindow() != &horizontalScrollBar) return false; + return true; +} + +AgView &AgView::setCursorLocation(cint loc) { + //LOGSECTION("AgView::setCursorLocation", Log::off); + LOGSECTION_OFF("AgView::setCursorLocation"); + //LOGSTACK; + //hideCursor(); + if (loc.y < 0) { + loc.y = 0; + } + if (loc.y >= nLines()) { + loc.y = nLines() - 1; + } + LOGV(cursorLocation); + LOGV(loc); + cursorLocation = loc; + unsigned oldCursor = cursorLine; + cursorLine = loc.y; + pixelCursor.x = xPosition(cursorLocation.x, getLine(cursorLine)); + pixelCursor.y = lineHeight()*cursorLine; + int repositionFlag = 0; + int vPos = verticalScrollBar.scrollBoxPosition(); + int vLimit = vPos + verticalScrollBar.visibleCount() - 1; + int hPos = horizontalScrollBar.scrollBoxPosition(); + int hLimit = hPos + horizontalScrollBar.visibleCount() - 4; + if (loc.y < vPos) { + verticalScrollBar.moveScrollBoxTo(loc.y); + repositionFlag = 1; + } + if (loc.y > vLimit) { + verticalScrollBar.moveScrollBoxTo(vPos + loc.y - vLimit); + repositionFlag = 1; + } + if (pixelCursor.x < hPos) { + int x; + int cursorX = cursorLocation.x - 5; + if (cursorX <= 0) { + x = 0; + } + else x = xPosition(cursorX, getLine(cursorLine)); + horizontalScrollBar.moveScrollBoxTo(x); + repositionFlag = 1; + } + if (pixelCursor.x > hLimit) { + int x = xPosition(cursorLocation.x+5, getLine(cursorLine)); + horizontalScrollBar.moveScrollBoxTo(hPos + x - hLimit); + repositionFlag = 1; + } + LOGV(vPos); + LOGV(vLimit); + LOGV(repositionFlag); + if (repositionFlag) reposition(); + if (cursorLineHighlight && cursorLine != oldCursor) { + repaintLine(oldCursor); + repaintLine(cursorLine); + } + setCursorPos(pixelCursor); + //showCursor(); + return *this; +} + +AgView &AgView::scrollTo(cint loc) { + //LOGSECTION("AgView::scrollTo", Log::on); + LOGSECTION_ON("AgView::scrollTo"); + //LOGSTACK; + //hideCursor(); + if (loc.y < 0) { + loc.y = 0; + } + if (loc.y >=nLines()) { + loc.y = nLines() - 1; + } + LOGV(cursorLocation); + LOGV(loc); + cint pixel; + pixel.x = xPosition(loc.x, getLine(loc.y)); + pixel.y = lineHeight()*loc.y; + int repositionFlag = 0; + int vPos = verticalScrollBar.scrollBoxPosition(); + int vLimit = vPos + verticalScrollBar.visibleCount() - 1; + int hPos = horizontalScrollBar.scrollBoxPosition(); + int hLimit = hPos + horizontalScrollBar.visibleCount() - 4; + if (loc.y < vPos) { + verticalScrollBar.moveScrollBoxTo(loc.y); + repositionFlag = 1; + } + if (loc.y > vLimit) { + verticalScrollBar.moveScrollBoxTo(vPos + loc.y - vLimit); + repositionFlag = 1; + } + if (pixel.x < hPos) { + int x; + int cursorX = loc.x - 5; + if (cursorX <= 0) { + x = 0; + } + else { + x = xPosition(cursorX, getLine(loc.y)); + } + horizontalScrollBar.moveScrollBoxTo(x); + repositionFlag = 1; + } + if (pixel.x > hLimit) { + int x = xPosition(loc.x+5, getLine(loc.y)); + horizontalScrollBar.moveScrollBoxTo(hPos + x - hLimit); + repositionFlag = 1; + } + LOGV(vPos); + LOGV(vLimit); + LOGV(repositionFlag); + if (repositionFlag) { + reposition(); + } + return *this; +} + + + +Boolean AgView::virtualKeyPress(IKeyboardEvent &event) { + //LOGSECTION("AgView::Virtual key press", Log::off); + LOGSECTION_OFF("AgView::Virtual key press"); + switch (event.virtualKey()) { + case IKeyboardEvent::up: { + if (!cursorLineHighlight && !cursorEnabled) { + int line = verticalScrollBar.scrollBoxPosition() - 1; + verticalScrollBar.moveScrollBoxTo(line); + line = verticalScrollBar.scrollBoxPosition(); + updateCursor(line); + return true; + } + int line = cursorLine; + if (cursorLine <= 0) { + messageBeep(); + return true; + } + if (cursorEnabled) { + hideCursor(); + } + cursorLine--; + LOGV(cursorLine) LCV(verticalScrollBar.scrollBoxPosition()); + if (cursorLine < verticalScrollBar.scrollBoxPosition()) { + if (cursorLineHighlight) { + repaintLine(line); + } + verticalScrollBar.moveScrollBoxTo(cursorLine); + reposition(); + } + else if (cursorLineHighlight) { + repaintLine(line); + repaintLine(cursorLine); + } + cursorLocation.y = cursorLine; + pixelCursor.x = xPosition(cursorLocation.x, getLine(cursorLine)); + pixelCursor.y = lineHeight()*cursorLine; + if (cursorEnabled) { + setCursorPos(pixelCursor).showCursor(); + } + return true; + } + case IKeyboardEvent::down: { + LOGSECTION("Cursor down one line"); + if (!cursorLineHighlight && !cursorEnabled) { + int line = verticalScrollBar.scrollBoxPosition() + 1; + verticalScrollBar.moveScrollBoxTo(line); + line = verticalScrollBar.scrollBoxPosition(); + updateCursor(line); + return true; + } + + int line = cursorLine; + if (cursorLine >= nLines() - 1) { + messageBeep(); + return true; + } + if (cursorEnabled) { + hideCursor(); + } + cursorLine++; + LOGV(cursorLine); + int bottomLine = + verticalScrollBar.scrollBoxPosition() + + verticalScrollBar.visibleCount() + - 1; + LOGV(line); + LOGV(cursorLine); + LOGV(bottomLine); + if (cursorLine > bottomLine) { + if (cursorLineHighlight) { + repaintLine(line); + } + int newLine = cursorLine - verticalScrollBar.visibleCount() + 1; + verticalScrollBar.moveScrollBoxTo(newLine); + reposition(); + } + else if (cursorLineHighlight) { + repaintLine(line); + repaintLine(cursorLine); + } + cursorLocation.y = cursorLine; + pixelCursor.x = xPosition(cursorLocation.x, getLine(cursorLine)); + pixelCursor.y = lineHeight()*cursorLine; + if (cursorEnabled) { + setCursorPos(pixelCursor).showCursor(); + } + return true; + } + case IKeyboardEvent::pageUp: { + LOGSECTION("AgView::pageUp"); + if (event.isCtrlDown()) { + if (cursorLine == 0) { + messageBeep(); + return true; + } + verticalScrollBar.moveScrollBoxTo(0); + int oldCursor = cursorLine; + cursorLine = 0; + if (cursorLineHighlight) { + repaintLine(oldCursor); + repaintLine(cursorLine); + } + reposition(); + cursorLocation.y = pixelCursor.y = 0; + if (cursorEnabled) { + setCursorPos(pixelCursor).showCursor(); + } + return true; + } + if (!cursorLineHighlight && !cursorEnabled) { + int line = verticalScrollBar.scrollBoxPosition(); + line -= verticalScrollBar.visibleCount(); + verticalScrollBar.moveScrollBoxTo(line); + line = verticalScrollBar.scrollBoxPosition(); + updateCursor(line); + return true; + } + int line = cursorLine; + if (cursorLine <= 0) { + return true; + } + if (cursorEnabled) { + hideCursor(); + } + cursorLine -= verticalScrollBar.visibleCount(); + if (cursorLine < 0) { + cursorLine = 0; + } + if (cursorLine < verticalScrollBar.scrollBoxPosition()) { + verticalScrollBar.moveScrollBoxTo(cursorLine); + reposition(); + } + else if (cursorLineHighlight) { + repaintLine(line); + } + cursorLocation.y = cursorLine; + pixelCursor.y = lineHeight()*cursorLine; + pixelCursor.x = xPosition(cursorLocation.x, getLine(cursorLine)); + if (cursorEnabled) { + setCursorPos(pixelCursor).showCursor(); + } + return true; + } + case IKeyboardEvent::pageDown: { + LOGSECTION("AgView::pageDown"); + if (event.isCtrlDown()) { + if (cursorLine >= nLines() - 1) { + messageBeep(); + return true; + } + //cursorLine = verticalScrollBar.scrollableRange().upperBound(); + cursorLine = nLines() - 1; + LOGV(cursorLine); + verticalScrollBar.moveScrollBoxTo(cursorLine); + updateCursor(cursorLine); + cursorLocation.y = cursorLine; + pixelCursor.y = cursorLine*lineHeight(); + return true; + } + if (!cursorLineHighlight && !cursorEnabled) { + int line = verticalScrollBar.scrollBoxPosition(); + line += verticalScrollBar.visibleCount(); + verticalScrollBar.moveScrollBoxTo(line); + line = verticalScrollBar.scrollBoxPosition(); + updateCursor(line); + } + int lastLine = nLines() - 1; + if (cursorLine >= lastLine) { + return true; + } + if (cursorEnabled) { + hideCursor(); + } + int line = cursorLine; + cursorLine += verticalScrollBar.visibleCount(); + pixelCursor.y = lineHeight()*cursorLine; + if (cursorLine > lastLine) { + cursorLine = lastLine; + } + if (cursorLine > verticalScrollBar.scrollBoxPosition()) { + int newLine = cursorLine - verticalScrollBar.visibleCount() + 1; + verticalScrollBar.moveScrollBoxTo(newLine); + reposition(); + } + else if (cursorLineHighlight) { + repaintLine(line); + } + cursorLocation.y = cursorLine; + pixelCursor.y = lineHeight()*cursorLine; + pixelCursor.x = xPosition(cursorLocation.x, getLine(cursorLine)); + if (cursorEnabled) { + setCursorPos(pixelCursor).showCursor(); + } + return true; + } + case IKeyboardEvent::left: { + if (cursorEnabled) { + hideCursor(); + if (cursorLocation.x > 0) { + cursorLocation.x--; + } + pixelCursor.x = xPosition(cursorLocation.x, getLine(cursorLine)); + if (pixelCursor.x < horizontalScrollBar.scrollBoxPosition()) { + int hPos = pixelCursor.x; + if (cursorLocation.x == 0) { + hPos = 0; + } + horizontalScrollBar.moveScrollBoxTo(hPos); + reposition(); + } + setCursorPos(pixelCursor); + showCursor(); + return true; + } + pixelCursor.x = horizontalScrollBar.scrollBoxPosition(); + pixelCursor.x -= avgCharWidth(); + if (pixelCursor.x < 0) { + pixelCursor.x = 0; + } + horizontalScrollBar.moveScrollBoxTo(pixelCursor.x); + reposition(); + updateCursor(); + return true; + } + case IKeyboardEvent::right: { + LOGS("cursor right"); + if (cursorEnabled) { + hideCursor(); + LOGS("cursor hidden"); + AgString line = getLine(cursorLine); + if (cursorLocation.x < line.size()) { + cursorLocation.x++; + } + pixelCursor.x = xPosition(cursorLocation.x, line); + int hPos = horizontalScrollBar.scrollBoxPosition(); + int rightEdge = hPos + horizontalScrollBar.visibleCount() - 4; + if (pixelCursor.x > rightEdge) { + hPos += pixelCursor.x - rightEdge; + horizontalScrollBar.moveScrollBoxTo(hPos); + reposition(); + } + setCursorPos(pixelCursor); + LOGS("cursor moved"); + showCursor(); + LOGS("cursor restored"); + return true; + } + pixelCursor.x = horizontalScrollBar.scrollBoxPosition(); + pixelCursor.x += avgCharWidth(); + int netWidth = tableWidth - horizontalScrollBar.visibleCount(); + if (pixelCursor.x > netWidth) { + pixelCursor.x = netWidth; + } + horizontalScrollBar.moveScrollBoxTo(pixelCursor.x); + reposition(); + cursorLocation.x = pixelCursor.x/avgCharWidth(); + updateCursor(); + return true; + } + case IKeyboardEvent::home: { + if (event.isCtrlDown()) { + if (cursorLine == 0) { + messageBeep(); + return true; + } + verticalScrollBar.moveScrollBoxTo(0); + int oldCursor = cursorLine; + cursorLine = 0; + if (cursorLineHighlight) { + repaintLine(oldCursor); + repaintLine(cursorLine); + } + reposition(); + cursorLocation.y = pixelCursor.y = 0; + if (cursorEnabled) { + setCursorPos(pixelCursor).showCursor(); + } + return true; + } + pixelCursor.x = avgCharWidth(); + cursorLocation.x = 0; + horizontalScrollBar.moveScrollBoxTo(0); + reposition(); + updateCursor(); + return true; + } + case IKeyboardEvent::end: { + if (event.isCtrlDown()) { + if (cursorLine >= nLines() - 1) { + messageBeep(); + return true; + } + //cursorLine = verticalScrollBar.scrollableRange().upperBound(); + cursorLine = nLines() - 1; + LOGV(cursorLine); + verticalScrollBar.moveScrollBoxTo(cursorLine); + updateCursor(cursorLine); + cursorLocation.y = cursorLine; + pixelCursor.y = cursorLine*lineHeight(); + return true; + } + if (cursorEnabled) { + LOGSECTION("AgView::end"); + hideCursor(); + AgString line = getLine(cursorLocation.y); + cursorLocation.x = line.size(); + LOGV(cursorLocation); + LOGV(line.size()); + pixelCursor.x = xPosition(cursorLocation.x, line); + LOGV(charPosition(pixelCursor.x, line)); + int hPos = horizontalScrollBar.scrollBoxPosition(); + int rightEdge = hPos + horizontalScrollBar.visibleCount() - 4; + if (pixelCursor.x > rightEdge) { + hPos += pixelCursor.x - rightEdge; + horizontalScrollBar.moveScrollBoxTo(hPos); + reposition(); + } + setCursorPos(pixelCursor); + LOGS("cursor moved"); + showCursor(); + return true; + } + pixelCursor.x = tableWidth - horizontalScrollBar.visibleCount(); + horizontalScrollBar.moveScrollBoxTo(pixelCursor.x); + reposition(); + updateCursor(); + return true; + } + } + return false; +} + +Boolean AgView::mouseClicked(IMouseClickEvent &event) { + //LOGSECTION("AgView::mouseClickEvent", Log::off); + LOGSECTION_OFF("AgView::mouseClickEvent"); + LOGV(event.mouseButton()); + LOGV(event.mouseAction()); + + if (event.controlWindow() == &columnHeadTitle + || event.controlWindow() == &verticalScrollBar + || event.controlWindow() == &horizontalScrollBar) { + if (event.mouseAction() == IMouseClickEvent::down) { + dataArea.setFocus(); + } + return false; + } + + if (ControlPanel::helpCursorSet) { + if (event.mouseAction() == IMouseClickEvent::down) { + ControlPanel::helpCursorSet = 0; + ControlPanel::resetCursor(); + } + } + + int line = event.mousePosition().y()/lineHeight(); + LOGV(line) LCV(verticalScrollBar.scrollBoxPosition()); + line += verticalScrollBar.scrollBoxPosition(); + LOGV(line); + //if (line >= nLines()) line = nLines() - 1; + + if (event.mouseButton() == IMouseClickEvent::button2) { + if (event.mouseAction() == IMouseClickEvent::down) { + rightButtonDown = true; + } + else if (event.mouseAction() == IMouseClickEvent::up) { + rightButtonDown = false; + } + return false; +/* + else if (event.mouseAction() == IMouseClickEvent::click) { + if (line == cursorLine) { + return true; + } + if (cursorLineHighlight) { + int oldLine = cursorLine; + cursorLine = line; + LOGV(oldLine) LCV(cursorLine); + repaintLine(oldLine); + repaintLine(cursorLine); + } + return true; + } +*/ + } + if (event.mouseButton() != IMouseClickEvent::button1) { + return false; + } + if (line >= nLines() && !mouseDown) { + if (!dataArea.hasFocus()) { + dataArea.setFocus(); + } + return false; + } + switch (event.mouseAction()) { + case IMouseClickEvent::down: { + if (event.windowUnderPointer() != dataArea.handle()) { + return false; + } + if (!cursorLineHighlight) { + return false; + } + dataArea.capturePointer(true); + mouseDownCursorLine = cursorLine; + //int line = event.mousePosition().y()/lineHeight(); + int offset = horizontalScrollBar.scrollBoxPosition(); + int whereX = event.mousePosition().x() + offset; + LOGV(cursorLine) LCV(offset) LCV(whereX); + AgString text = getLine(line); + cint loc(charPosition(whereX, text), line); + LOGV(loc); + cursorLocation = loc; + if (line != cursorLine) { + cursorLine = line; + if (cursorLineHighlight) { + LOGV(mouseDownCursorLine) LCV(cursorLine); + repaintLine(mouseDownCursorLine); + repaintLine(cursorLine); + } + onSelect(); + } + mouseDown = true; + return false; + } + case IMouseClickEvent::up: { + mouseDown = false; + dataArea.capturePointer(false); + return false; + } + case IMouseClickEvent::click: { + if (event.windowUnderPointer() != dataArea.handle()) { + return false; + } + dataArea.setFocus(); + //if (line == mouseDownCursorLine) { + // onSelect(); + //} + return false; + } + case IMouseClickEvent::doubleClick: { + dataArea.setFocus(); + //onSelect(); + onEnter(); + return false; + } + } + return false; +} + +Boolean AgView::mouseMoved(IMouseEvent &event) { + if (!mouseDown) { + return false; + } + if (!cursorLineHighlight) { + return false; + } + if (mouseTimer.isStarted()) { + mouseTimer.stop(); + } + int mouseY = event.mousePosition().y(); + if (mouseY < 0) { + mouseY -= lineHeight(); + } + int mouseLine = mouseY/lineHeight(); + int topLine = verticalScrollBar.scrollBoxPosition(); + //LOGSECTION("Mouse moved", Log::off); + LOGSECTION_OFF("Mouse moved"); + LOGV(topLine) LCV(mouseLine); + dragMouse(topLine, mouseLine); + topLine = verticalScrollBar.scrollBoxPosition(); + int belowLine = topLine + verticalScrollBar.visibleCount(); + if (mouseLine >= topLine && mouseLine < belowLine) { + return true; + } + IReference<ITimerFn> timerFn(new MouseDragTimer(this, topLine, mouseLine)); + mouseTimer.start(timerFn, 50); + LOGS("timer started"); + return false; +} + +void AgView::dragMouse(int topLine, int mouseLine) { + //LOGSECTION("Agview::dragMouse", Log::off); + LOGSECTION_OFF("Agview::dragMouse"); + int bottomLine = topLine + verticalScrollBar.visibleCount() - 1; + int line = topLine + mouseLine; + if (line < 0) { + line = 0; + } + if (line >= nLines()) { + line = nLines() - 1; + } + if (line == cursorLine) { + return; + } + int oldLine = cursorLine; + cursorLocation.y = cursorLine = line; + pixelCursor.y = lineHeight()*cursorLine; + if (cursorLine < topLine) { + if (cursorLineHighlight) repaintLine(oldLine); + verticalScrollBar.moveScrollBoxTo(cursorLine); + reposition(); + return; + } + if (cursorLine > bottomLine) { + if (cursorLineHighlight) { + repaintLine(oldLine); + } + verticalScrollBar.moveScrollBoxTo(topLine + cursorLine - bottomLine); + reposition(); + return; + } + + if (cursorLineHighlight) { + repaintLine(oldLine); + repaintLine(cursorLine); + } + return; +} + +void AgView::mouseDragTimerInterrupt(int &topLine, int mouseLine) { + //LOGSECTION("AgView::mouseDragTimer", Log::off); + LOGSECTION_OFF("AgView::mouseDragTimer"); + LOGV(topLine) LCV(mouseLine) LCV(cursorLine); + if (!mouseDown || topLine + mouseLine == cursorLine) { + mouseTimer.stop(); + LOGV(mouseDown); + LOGV(topLine) LCV(verticalScrollBar.scrollBoxPosition()); + return; + } + if (topLine + mouseLine != cursorLine) { + dragMouse(topLine, mouseLine); + } + topLine = verticalScrollBar.scrollBoxPosition(); +} + +AgView::MouseDragTimer::MouseDragTimer(AgView * window_, int topLine_, + int mouseLine_) + : window(window_) + , topLine(topLine_) + , mouseLine(mouseLine_) +{} + +void AgView::MouseDragTimer::timerExpired(unsigned long) { + //LOGSECTION("AgView::MouseDragTimer::timerExpired", Log::off); + LOGSECTION_OFF("AgView::MouseDragTimer::timerExpired"); + window->mouseDragTimerInterrupt(topLine, mouseLine); +}