Beispiel #1
0
QRect RectDrawing::remainingRect(DrawParams *dp)
{
    if (!dp) {
        dp = drawParams();
    }

    if ((_usedTopLeft > 0) ||
            (_usedTopCenter > 0) ||
            (_usedTopRight > 0)) {
        if (dp->rotated()) {
            _rect.setLeft(_rect.left() + _fontHeight);
        } else {
            _rect.setTop(_rect.top() + _fontHeight);
        }
    }

    if ((_usedBottomLeft > 0) ||
            (_usedBottomCenter > 0) ||
            (_usedBottomRight > 0)) {
        if (dp->rotated()) {
            _rect.setRight(_rect.right() - _fontHeight);
        } else {
            _rect.setBottom(_rect.bottom() - _fontHeight);
        }
    }
    return _rect;
}
Beispiel #2
0
void WorldUIView::draw() {	
	if(isVisible()){	
		drawBg();
		drawSurface();
		drawObjects();
		drawBorder();
		drawParams();

		UIView::draw();
	}		
	
}
Beispiel #3
0
bool RectDrawing::drawField(QPainter *p, int f, DrawParams *dp)
{
    if (!dp) {
        dp = drawParams();
    }

    if (!_fm) {
        _fm = new QFontMetrics(dp->font());
        _fontHeight = _fm->height();
    }

    QRect r = _rect;

    int h = _fontHeight;
    bool rotate = dp->rotated();
    int width   = (rotate ? r.height() : r.width()) - 4;
    int height  = (rotate ? r.width() : r.height());
    int lines   = height / h;

    // stop if there is no space available
    if (lines < 1) {
        return false;
    }

    // calculate free space in first line (<unused>)
    int pos = dp->position(f);
    if (pos == DrawParams::Default) {
        switch (f % 4) {
        case 0: pos = DrawParams::TopLeft; break;
        case 1: pos = DrawParams::TopRight; break;
        case 2: pos = DrawParams::BottomRight; break;
        case 3: pos = DrawParams::BottomLeft; break;
        }
    }

    int unused = 0;
    bool isBottom = false;
    bool isCenter = false;
    bool isRight = false;
    int *used = 0;
    switch (pos) {
    case DrawParams::TopLeft:
        used = &_usedTopLeft;
        if (_usedTopLeft == 0) {
            if (_usedTopCenter) {
                unused = (width - _usedTopCenter) / 2;
            } else {
                unused = width - _usedTopRight;
            }
        }
        break;

    case DrawParams::TopCenter:
        isCenter = true;
        used = &_usedTopCenter;
        if (_usedTopCenter == 0) {
            if (_usedTopLeft > _usedTopRight) {
                unused = width - 2 * _usedTopLeft;
            } else {
                unused = width - 2 * _usedTopRight;
            }
        }
        break;

    case DrawParams::TopRight:
        isRight = true;
        used = &_usedTopRight;
        if (_usedTopRight == 0) {
            if (_usedTopCenter) {
                unused = (width - _usedTopCenter) / 2;
            } else {
                unused = width - _usedTopLeft;
            }
        }
        break;

    case DrawParams::BottomLeft:
        isBottom = true;
        used = &_usedBottomLeft;
        if (_usedBottomLeft == 0) {
            if (_usedBottomCenter) {
                unused = (width - _usedBottomCenter) / 2;
            } else {
                unused = width - _usedBottomRight;
            }
        }
        break;

    case DrawParams::BottomCenter:
        isCenter = true;
        isBottom = true;
        used = &_usedBottomCenter;
        if (_usedBottomCenter == 0) {
            if (_usedBottomLeft > _usedBottomRight) {
                unused = width - 2 * _usedBottomLeft;
            } else {
                unused = width - 2 * _usedBottomRight;
            }
        }
        break;

    case DrawParams::BottomRight:
        isRight = true;
        isBottom = true;
        used = &_usedBottomRight;
        if (_usedBottomRight == 0) {
            if (_usedBottomCenter) {
                unused = (width - _usedBottomCenter) / 2;
            } else {
                unused = width - _usedBottomLeft;
            }
        }
        break;
    }
    if (isBottom) {
        if ((_usedTopLeft > 0) ||
                (_usedTopCenter > 0) ||
                (_usedTopRight > 0)) {
            lines--;
        }
    } else if (!isBottom) {
        if ((_usedBottomLeft > 0) ||
                (_usedBottomCenter > 0) ||
                (_usedBottomRight > 0)) {
            lines--;
        }
    }
    if (lines < 1) {
        return false;
    }

    int y = isBottom ? height - h : 0;

    if (unused < 0) {
        unused = 0;
    }
    if (unused == 0) {
        // no space available in last line at this position
        y = isBottom ? (y - h) : (y + h);
        lines--;

        if (lines < 1) {
            return false;
        }

        // new line: reset used space
        if (isBottom) {
            _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0;
        } else {
            _usedTopLeft = _usedTopCenter = _usedTopRight = 0;
        }

        unused = width;
    }

    // stop as soon as possible when there is no space for "..."
    static int dotW = 0;
    if (!dotW) {
        dotW = _fm->width("...");
    }
    if (width < dotW) {
        return false;
    }

    // get text and pixmap now, only if we need to, because it is possible
    // that they are calculated on demand (and this can take some time)
    QString name = dp->text(f);
    if (name.isEmpty()) {
        return 0;
    }
    QPixmap pix = dp->pixmap(f);

    // check if pixmap can be drawn
    int pixW = pix.width();
    int pixH = pix.height();
    int pixY = 0;
    bool pixDrawn = true;
    if (pixW > 0) {
        pixW += 2; // X distance from pix
        if ((width < pixW + dotW) || (height < pixH)) {
            // do not draw
            pixW = 0;
        } else {
            pixDrawn = false;
        }
    }

    // width of text and pixmap to be drawn
    int w = pixW + _fm->width(name);

    // if we have limited space at 1st line:
    // use it only if whole name does fit in last line...
    if ((unused < width) && (w > unused)) {
        y = isBottom ? (y - h) : (y + h);
        lines--;

        if (lines < 1) {
            return false;
        }

        // new line: reset used space
        if (isBottom) {
            _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0;
        } else {
            _usedTopLeft = _usedTopCenter = _usedTopRight = 0;
        }
    }

    p->save();
    p->setPen((qGray(dp->backColor().rgb()) > 100) ? Qt::black : Qt::white);
    p->setFont(dp->font());
    if (rotate) {
        //p->translate(r.x()+2, r.y()+r.height());
        p->translate(r.x(), r.y() + r.height() - 2);
        p->rotate(270);
    } else {
        p->translate(r.x() + 2, r.y());
    }
    // adjust available lines according to maxLines
    int max = dp->maxLines(f);
    if ((max > 0) && (lines > max)) {
        lines = max;
    }
    /* loop over name parts to break up string depending on available width.
     * every char category change is supposed a possible break,
     * with the exception Uppercase=>Lowercase.
     * It is good enough for numbers, Symbols...
     *
     * If the text is to be written at the bottom, we start with the
     * end of the string (so everything is reverted)
    */
    QString remaining;
    int origLines = lines;
    while (lines > 0) {

        // more than one line: search for line break
        if (w > width && lines > 1) {
            int breakPos;

            if (!isBottom) {
                w = pixW + findBreak(breakPos, name, _fm, width - pixW);

                remaining = name.mid(breakPos);
                // remove space on break point
                if (name[breakPos - 1].category() == QChar::Separator_Space) {
                    name = name.left(breakPos - 1);
                } else {
                    name = name.left(breakPos);
                }
            } else { // bottom
                w = pixW + findBreakBackwards(breakPos, name, _fm, width - pixW);

                remaining = name.left(breakPos);
                // remove space on break point
                if (name[breakPos].category() == QChar::Separator_Space) {
                    name = name.mid(breakPos + 1);
                } else {
                    name = name.mid(breakPos);
                }
            }
        } else {
            remaining.clear();
        }
        /* truncate and add ... if needed */
        if (w > width) {
            name = _fm->elidedText(name, Qt::ElideRight, width - pixW);
            w = _fm->width(name) + pixW;
        }

        int x = 0;
        if (isCenter) {
            x = (width - w) / 2;
        } else if (isRight) {
            x = width - w;
        }
        if (!pixDrawn) {
            pixY = y + (h - pixH) / 2; // default: center vertically
            if (pixH > h) {
                pixY = isBottom ? y - (pixH - h) : y;
            }

            p->drawPixmap(x, pixY, pix);

            // for distance to next text
            pixY = isBottom ? (pixY - h - 2) : (pixY + pixH + 2);
            pixDrawn = true;
        }
        p->drawText(x + pixW, y,
                    width - pixW, h,
                    Qt::AlignLeft, name);
        y = isBottom ? (y - h) : (y + h);
        lines--;

        if (remaining.isEmpty()) {
            break;
        }
        name = remaining;
        w = pixW + _fm->width(name);
    }

    // make sure the pix stays visible
    if (pixDrawn && (pixY > 0)) {
        if (isBottom && (pixY < y)) {
            y = pixY;
        }
        if (!isBottom && (pixY > y)) {
            y = pixY;
        }
    }

    if (origLines > lines) {
        // if only 1 line written, do not reset _used* vars
        if (lines - origLines > 1) {
            if (isBottom) {
                _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0;
            } else {
                _usedTopLeft = _usedTopCenter = _usedTopRight = 0;
            }
        }

        // take back one line
        y = isBottom ? (y + h) : (y - h);
        if (used) {
            *used = w;
        }
    }

    // update free space
    if (!isBottom) {
        if (rotate) {
            _rect.setRect(r.x() + y, r.y(), r.width() - y, r.height());
        } else {
            _rect.setRect(r.x(), r.y() + y, r.width(), r.height() - y);
        }
    } else {
        if (rotate) {
            _rect.setRect(r.x(), r.y(), y + h, r.height());
        } else {
            _rect.setRect(r.x(), r.y(), r.width(), y + h);
        }
    }

    p->restore();

    return true;
}
Beispiel #4
0
void RectDrawing::drawBack(QPainter *p, DrawParams *dp)
{
    if (!dp) {
        dp = drawParams();
    }
    if (_rect.width() <= 0 || _rect.height() <= 0) {
        return;
    }

    QRect r = _rect;
    QColor normal = dp->backColor();
    if (dp->selected()) {
        normal = normal.light();
    }
    bool isCurrent = dp->current();

    if (dp->drawFrame() || isCurrent) {
        // 3D raised/sunken frame effect...
        QColor high = normal.light();
        QColor low = normal.dark();
        p->setPen(isCurrent ? low : high);
        p->drawLine(r.left(), r.top(), r.right(), r.top());
        p->drawLine(r.left(), r.top(), r.left(), r.bottom());
        p->setPen(isCurrent ? high : low);
        p->drawLine(r.right(), r.top(), r.right(), r.bottom());
        p->drawLine(r.left(), r.bottom(), r.right(), r.bottom());
        r.setRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2);
    }
    if (r.width() <= 0 || r.height() <= 0) {
        return;
    }
    if (dp->shaded() && (r.width() > 0 && r.height() > 0)) {
        // adjustment for drawRect semantic in Qt4: decrement height/width
        r.setRect(r.x(), r.y(), r.width() - 1, r.height() - 1);

        // some shading
        bool goDark = qGray(normal.rgb()) > 128;
        int rBase, gBase, bBase;
        normal.getRgb(&rBase, &gBase, &bBase);
        p->setBrush(Qt::NoBrush);

        // shade parameters:
        int d = 7;
        float factor = 0.1, forth = 0.7, back1 = 0.9, toBack2 = .7, back2 = 0.97;

        // coefficient corrections because of rectangle size
        int s = r.width();
        if (s > r.height()) {
            s = r.height();
        }
        if (s < 100) {
            forth -= .3  * (100 - s) / 100;
            back1 -= .2  * (100 - s) / 100;
            back2 -= .02 * (100 - s) / 100;
        }

        // maximal color difference
        int rDiff = goDark ? -rBase / d : (255 - rBase) / d;
        int gDiff = goDark ? -gBase / d : (255 - gBase) / d;
        int bDiff = goDark ? -bBase / d : (255 - bBase) / d;

        QColor shadeColor;
        while (factor < .95 && (r.width() >= 0 && r.height() >= 0)) {
            shadeColor.setRgb((int)(rBase + factor * rDiff + .5),
                              (int)(gBase + factor * gDiff + .5),
                              (int)(bBase + factor * bDiff + .5));
            p->setPen(shadeColor);
            p->drawRect(r);
            r.setRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2);
            factor = 1.0 - ((1.0 - factor) * forth);
        }

        // and back (1st half)
        while (factor > toBack2 && (r.width() >= 0 && r.height() >= 0)) {
            shadeColor.setRgb((int)(rBase + factor * rDiff + .5),
                              (int)(gBase + factor * gDiff + .5),
                              (int)(bBase + factor * bDiff + .5));
            p->setPen(shadeColor);
            p->drawRect(r);
            r.setRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2);
            factor = 1.0 - ((1.0 - factor) / back1);
        }

        // and back (2nd half)
        while (factor > .01 && (r.width() >= 0 && r.height() >= 0)) {
            shadeColor.setRgb((int)(rBase + factor * rDiff + .5),
                              (int)(gBase + factor * gDiff + .5),
                              (int)(bBase + factor * bDiff + .5));
            p->setPen(shadeColor);
            p->drawRect(r);
            r.setRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2);
            factor = factor * back2;
        }

        normal = shadeColor;
        // for filling, width and height has to be incremented again
        r.setRect(r.x(), r.y(), r.width() + 1, r.height() + 1);
    }

    // fill inside
    p->fillRect(r, normal);
}
Beispiel #5
0
bool RectDrawing::drawField(QPainter* p, int f, DrawParams* dp)
{
  if (!dp) dp = drawParams();

  if (!_fm) {
    _fm = new QFontMetrics(dp->font());
    _fontHeight = _fm->height();
  }

  QRect r = _rect;

//  if (0) Debug(90100) << "DrawField: Rect " << r.x() << "/" << r.y()
//		   << " - " << r.width() << "x" << r.height() << endl;

  int h = _fontHeight;
  bool rotate = dp->rotated();
  int width   = (rotate ? r.height() : r.width()) -4;
  int height  = (rotate ? r.width() : r.height());
  int lines   = height / h;

  // stop if we have no space available
  if (lines<1) return false;

  // calculate free space in first line (<unused>)
  int pos = dp->position(f);
  if (pos == DrawParams::Default) {
    switch(f%4) {
    case 0: pos = DrawParams::TopLeft; break;
    case 1: pos = DrawParams::TopRight; break;
    case 2: pos = DrawParams::BottomRight; break;
    case 3: pos = DrawParams::BottomLeft; break;
    }
  }

  int unused = 0;
  bool isBottom = false;
  bool isCenter = false;
  bool isRight = false;
  int* used = 0;
  switch(pos) {
  case DrawParams::TopLeft:
    used = &_usedTopLeft;
    if (_usedTopLeft == 0) {
      if (_usedTopCenter)
        unused = (width - _usedTopCenter)/2;
      else
        unused = width - _usedTopRight;
    }
    break;

  case DrawParams::TopCenter:
    isCenter = true;
    used = &_usedTopCenter;
    if (_usedTopCenter == 0) {
      if (_usedTopLeft > _usedTopRight)
        unused = width - 2 * _usedTopLeft;
      else
        unused = width - 2 * _usedTopRight;
    }
    break;

  case DrawParams::TopRight:
    isRight = true;
    used = &_usedTopRight;
    if (_usedTopRight == 0) {
      if (_usedTopCenter)
        unused = (width - _usedTopCenter)/2;
      else
        unused = width - _usedTopLeft;
    }
    break;

  case DrawParams::BottomLeft:
    isBottom = true;
    used = &_usedBottomLeft;
    if (_usedBottomLeft == 0) {
      if (_usedBottomCenter)
        unused = (width - _usedBottomCenter)/2;
      else
        unused = width - _usedBottomRight;
    }
    break;

  case DrawParams::BottomCenter:
    isCenter = true;
    isBottom = true;
    used = &_usedBottomCenter;
    if (_usedBottomCenter == 0) {
      if (_usedBottomLeft > _usedBottomRight)
        unused = width - 2 * _usedBottomLeft;
      else
        unused = width - 2 * _usedBottomRight;
    }
    break;

  case DrawParams::BottomRight:
    isRight = true;
    isBottom = true;
    used = &_usedBottomRight;
    if (_usedBottomRight == 0) {
      if (_usedBottomCenter)
        unused = (width - _usedBottomCenter)/2;
      else
        unused = width - _usedBottomLeft;
    }
    break;
  }

  if (isBottom) {
    if ((_usedTopLeft >0) ||
        (_usedTopCenter >0) ||
        (_usedTopRight >0))
      lines--;
  }
  else if (!isBottom) {
    if ((_usedBottomLeft >0) ||
        (_usedBottomCenter >0) ||
        (_usedBottomRight >0))
      lines--;
  }
  if (lines<1) return false;


  int y = isBottom ? height - h : 0;

  if (unused < 0) unused = 0;
  if (unused == 0) {
    // no space available in last line at this position
    y = isBottom ? (y-h) : (y+h);
    lines--;

    if (lines<1) return false;

    // new line: reset used space
    if (isBottom)
      _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0;
    else
      _usedTopLeft = _usedTopCenter = _usedTopRight = 0;

    unused = width;
  }

  // stop as soon as possible when there's no space for "..."
  static int dotW = 0;
  if (!dotW) dotW = _fm->width("...");
  if (width < dotW) return false;

  // get text and pixmap now, only if we need to, because it is possible
  // that they are calculated on demand (and this can take some time)
  QString name = dp->text(f);
  if (name.isEmpty()) return 0;
  QPixmap pix = dp->pixmap(f);

  // check if pixmap can be drawn
  int pixW = pix.width();
  int pixH = pix.height();
  int pixY = 0;
  bool pixDrawn = true;
  if (pixW>0) {
    pixW += 2; // X distance from pix
    if ((width < pixW + dotW) || (height < pixH)) {
      // don't draw
      pixW = 0;
    }
    else
      pixDrawn = false;
  }

  // width of text and pixmap to be drawn
  int w = pixW + _fm->width(name);

//  if (0) Debug(90100) << "  For '" << name << "': Unused " << unused
//		   << ", StrW " << w << ", Width " << width << endl;

  // if we have limited space at 1st line:
  // use it only if whole name does fit in last line...
  if ((unused < width) && (w > unused)) {
    y = isBottom ? (y-h) : (y+h);
    lines--;

    if (lines<1) return false;

    // new line: reset used space
    if (isBottom)
      _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0;
    else
      _usedTopLeft = _usedTopCenter = _usedTopRight = 0;
  }

  p->save();
  p->setPen( (qGray(dp->backColor().rgb())>100) ? Qt::black : Qt::white);
  p->setFont(dp->font());
  if (rotate) {
    //p->translate(r.x()+2, r.y()+r.height());
    p->translate(r.x(), r.y()+r.height()-2);
    p->rotate(270);
  }
  else
    p->translate(r.x()+2, r.y());


  // adjust available lines according to maxLines
  int max = dp->maxLines(f);
  if ((max > 0) && (lines>max)) lines = max;

  /* loop over name parts to break up string depending on available width.
   * every char category change is supposed a possible break,
   * with the exception Uppercase=>Lowercase.
   * It's good enough for numbers, Symbols...
   *
   * If the text is to be written at the bottom, we start with the
   * end of the string (so everything is reverted)
   */
  QString remaining;
  int origLines = lines;
  while (lines>0) {

    if (w>width && lines>1) {
      int lastBreakPos = name.length(), lastWidth = w;
      int len = name.length();
      QChar::Category caOld, ca;

      if (!isBottom) {
        // start with comparing categories of last 2 chars
        caOld = name[len-1].category();
        while (len>2) {
          len--;
          ca = name[len-1].category();
          if (ca != caOld) {
            // "Aa" has no break between...
            if (ca == QChar::Letter_Uppercase &&
                caOld == QChar::Letter_Lowercase) {
              caOld = ca;
              continue;
            }
            caOld = ca;
            lastBreakPos = len;
            w = pixW + _fm->width(name, len);
            lastWidth = w;
            if (w <= width) break;
          }
        }
        w = lastWidth;
        remaining = name.mid(lastBreakPos);
        // remove space on break point
        if (name[lastBreakPos-1].category() == QChar::Separator_Space)
          name = name.left(lastBreakPos-1);
        else
          name = name.left(lastBreakPos);
      }
      else { // bottom
        int l = len;
        caOld = name[l-len].category();
        while (len>2) {
          len--;
          ca = name[l-len].category();

          if (ca != caOld) {
            // "Aa" has no break between...
            if (caOld == QChar::Letter_Uppercase &&
                ca == QChar::Letter_Lowercase) {
              caOld = ca;
              continue;
            }
            caOld = ca;
            lastBreakPos = len;
            w = pixW + _fm->width(name.right(len));
            lastWidth = w;
            if (w <= width) break;
          }
        }
        w = lastWidth;
        remaining = name.left(l-lastBreakPos);
        // remove space on break point
        if (name[l-lastBreakPos].category() == QChar::Separator_Space)
          name = name.right(lastBreakPos-1);
        else
          name = name.right(lastBreakPos);
      }
    }
    else
      remaining = QString::null;

    /* truncate and add ... if needed */
    if (w>width) {
      int len = name.length();
      w += dotW;
      while (len>2 && (w > width)) {
        len--;
        w = pixW + _fm->width(name, len) + dotW;
      }
      // stop drawing: we cannot draw 2 chars + "..."
      if (w>width) break;

      name = name.left(len) + "...";
    }

    int x = 0;
    if (isCenter)
      x = (width - w)/2;
    else if (isRight)
      x = width - w;

    if (!pixDrawn) {
        pixY = y+(h-pixH)/2; // default: center vertically
        if (pixH > h) pixY = isBottom ? y-(pixH-h) : y;

	p->drawPixmap( x, pixY, pix);

        // for distance to next text
	pixY = isBottom ? (pixY - h - 2) : (pixY + pixH + 2);
	pixDrawn = true;
    }


//    if (0) Debug(90100) << "  Drawing '" << name << "' at "
//		     << x+pixW << "/" << y << endl;

    p->drawText( x+pixW, y+10,
		 width - pixW, h,
		 Qt::AlignVCenter, name);
    y = isBottom ? (y-h) : (y+h);
    lines--;

    if (remaining.isEmpty()) break;
    name = remaining;
    w = pixW + _fm->width(name);
  }

  // make sure the pix stays visible
  if (pixDrawn && (pixY>0)) {
    if (isBottom && (pixY<y)) y = pixY;
    if (!isBottom && (pixY>y)) y = pixY;
  }

  if (origLines > lines) {
    // if only 1 line written, don't reset _used* vars
    if (lines - origLines >1) {
      if (isBottom)
        _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0;
      else
        _usedTopLeft = _usedTopCenter = _usedTopRight = 0;
    }

    // take back one line
    y = isBottom ? (y+h) : (y-h);
    if (used) *used = w;
  }

  // update free space
  if (!isBottom) {
    if (rotate)
      _rect.setRect(r.x()+y, r.y(), r.width()-y, r.height());
    else
      _rect.setRect(r.x(), r.y()+y, r.width(), r.height()-y);
  }
  else {
    if (rotate)
      _rect.setRect(r.x(), r.y(), y+h, r.height());
    else
      _rect.setRect(r.x(), r.y(), r.width(), y+h);
  }

  p->restore();

  return true;
}