Exemplo n.º 1
0
Drawable::Drawable (const Drawable& other)
    : Component (other.getName())
{
    setInterceptsMouseClicks (false, false);
    setPaintingIsUnclipped (true);

    setComponentID (other.getComponentID());
    setTransform (other.getTransform());

    if (auto* clipPath = other.drawableClipPath.get())
        setClipPath (clipPath->createCopy());
}
Exemplo n.º 2
0
Arquivo: WPainter.C Projeto: nkabir/wt
void WPainter::drawText(const WRectF& rectangle,
                        WFlags<AlignmentFlag> alignmentFlags,
                        TextFlag textFlag,
                        const WString& text)
{
    if (textFlag == TextSingleLine)
        drawText(rectangle, alignmentFlags, text);
    else {
        if (!(alignmentFlags & AlignVerticalMask))
            alignmentFlags |= AlignTop;
        if (!(alignmentFlags & AlignHorizontalMask))
            alignmentFlags |= AlignLeft;

        if (device_->features() & WPaintDevice::CanWordWrap)
            device_->drawText(rectangle.normalized(), alignmentFlags, textFlag, text);
        else if (device_->features() & WPaintDevice::HasFontMetrics) {
#ifndef WT_TARGET_JAVA
            MultiLineTextRenderer renderer(*this, rectangle);

            AlignmentFlag horizontalAlign = alignmentFlags & AlignHorizontalMask;
            AlignmentFlag verticalAlign = alignmentFlags & AlignVerticalMask;

            /*
             * Oh irony: after all these years of hating CSS, we now
             * implemented an XHTML renderer for which we need to use the
             * same silly workarounds to render the text with all possible
             * alignment options
             */
            WStringStream s;
            s << "<table style=\"width:" << (int)rectangle.width() << "px;\""
              "cellspacing=\"0\"><tr>"
              "<td style=\"padding:0px;height:" << (int)rectangle.height() <<
              "px;color:" << pen().color().cssText()
              << ";text-align:";

            switch (horizontalAlign) {
            case AlignLeft:
                s << "left";
                break;
            case AlignRight:
                s << "right";
                break;
            case AlignCenter:
                s << "center";
                break;
            default:
                break;
            }

            s << ";vertical-align:";

            switch (verticalAlign) {
            case AlignTop:
                s << "top";
                break;
            case AlignBottom:
                s << "bottom";
                break;
            case AlignMiddle:
                s << "middle";
                break;
            default:
                break;
            }

            s << ";" << font().cssText(false);

            s << "\">"
              << WWebWidget::escapeText(text, true).toUTF8()
              << "</td></tr></table>";

            save();

            /*
             * FIXME: what if there was already a clip path? We need to combine
             * them ...
             */
            WPainterPath p;
            p.addRect(rectangle.x() + 1, rectangle.y() + 1, rectangle.width() - 2, rectangle.height() - 2);
            setClipPath(p);
            setClipping(true);
            renderer.render(WString::fromUTF8(s.str()));
            restore();
#endif // WT_TARGET_JAVA
        } else
            throw WException("WPainter::drawText(): device does not support "
                             "TextWordWrap or FontMetrics");
    }
}
Exemplo n.º 3
0
///
/// iconPie(): Draws a pie with a given color on the individual icon. Each pie corresponds to one 
/// categorical variable. The color corresponds to the level in that variable. 
///
void DrawingCanvas::iconPie( double x, double y, Individual *pIndividual ){
	
	//
	// Handle virtual individuals:
	//
	if(pIndividual->isVirtual()){
		
		//_body << "<circle cx=\"" << x << "\" cy=\"" << y << "\" r=\"" << 0.5*DrawingMetrics::getScalingFactor() << "\"";
		//_body << " class=\"thinLine\"";
		//_body << "/>\n";
		return;
		
	}
	//
	// Get here if non-virtual:
	//
	
	//
	// How many sections are there?
	//
	unsigned sections = pIndividual->getDataTable()->getIconColumnCount();
	if(!sections){
		//
		// No affected fields : Draw a small circle in the middle:
		// (Nice for debugging -- otherwise comment out )
		//
		//_body << "<circle cx=\"" << x << "\" cy=\"" << y << "\" r=\"" << 0.5*DrawingMetrics::getScalingFactor() << "\"";
		//_body << " class=\"thinLine\"";
		//_body << "/>\n";
		return;
	}
	
	//
	// Setup clipping Id, if needed:
	//
	std::string clipId = pIndividual->getId().get() + "_clipPath";
	double radius=DrawingMetrics::getIconRadius();
	bool isMale = false;
	if( pIndividual->getGender().getEnum()==Gender::MALE ){
		
		setClipPath(x,y,clipId);
		//
		// Increase radius for clipping:
		//
		radius*=Number::SQRT_TWO;
		isMale = true;
		_body << "<g clip-path=\"url(#" << clipId << ")\">\n";
		
	}else{
		//
		// Empty g with no clipping for female:
		//
		_body << "<g>\n";
		
	}
	
	//
	// Iterate over _iconColumns:
	//
	const DataTable *pDT = pIndividual->getDataTable();
	double arcAngle = 2.0*Number::PI/sections;
	double startAngle = 0.5*Number::PI - arcAngle;
	double endAngle   = startAngle+arcAngle;
	for(unsigned i=0;i<sections;i++){
		//
		// Get the data column of the ith icon column:
		//
		DataColumn * pDC = pDT->getColumn( pDT->getIconColumnIndex(i) );
		//
		// Get the UniqueList for this column:
		//
		const UniqueList * pUL = pDC->getUniqueList();
		
		//
		// Only process if there are some non-missing levels
		// present:
		//
		if(!pUL->getLevels()) continue;
		
		//
		// What is the level and label in the UniqueList corresponding to the data value
		// for this individual?
		//
		unsigned level;
		std::string label;
		pUL->getOrdinalAndLabelForKey( pDC->getDataAtIndex( pIndividual->getRowIndex() ),label,level );
		//
		// UniqueList ordinals are 1-offset, so we should only get zero back
		// if the key was not found, which should never happen:
		//
		if(level==0) throw Exception("DrawingCanvas::iconPie()","UniqueList returned ordinal 0.");
		//
		// Level is 1-offset, so subtract:
		//
		level--;
		
		//
		// Get the color series corresponding to this icon column:
		//
		// NOTA BENE: (1) IF there is only one section, we use the 
		//                blackAndWhite series
		//                UNLESS there is a color override.
		//
		//            (2) OTHERWISE if there are more than one section, 
		//                we use the color series
		//                UNLESS there is a black-and-white override.
		//
		ColorSeries *pCS;
		if(sections==1){
			if(DrawingMetrics::getColor()) pCS = pDT->getColorSeriesFromStack(i);
			else                           pCS = pDT->getBlackAndWhiteSeriesFromStack(i);
		}else{
			if(DrawingMetrics::getBlackAndWhite()) pCS = pDT->getBlackAndWhiteSeriesFromStack(i);
			else                                   pCS = pDT->getColorSeriesFromStack(i);
		}
		//
		// Assume reversed for now:
		//
		bool reversed=true;
		std::string arcClass="blackInkLetter";
		if(!pCS->reversedSeriesUseBlackInkAtLevel(level)) arcClass="whiteInkLetter";
		
		//
		// If the number of sections is small, use a larger font size
		//
		
		if(sections == 1)      arcClass += "_1";
		else if(sections == 2) arcClass += "_2";
		else if(sections == 3) arcClass += "_3";
		arc(x,y,radius,startAngle,endAngle,(reversed?pCS->reversedSeriesGetColorAtLevel(level):pCS->getColorAtLevel(level)),label,arcClass,isMale);
		startAngle+=arcAngle;
		endAngle+=arcAngle;
		
		// For the first time draw the icon legend too:
		if(!_iconLegendFlag){
			_iconLegendFlag = true;
			_iconLegend.setPedigreeTable(pDT);
		}
		
	}
	_body << "</g>\n";
	return;
	
}
Exemplo n.º 4
0
///
/// iconQuadrantFill(): Shade quadrants of the icon to indicate specific levels.
///                     This method has a limit of 16 distinct levels.
///
void DrawingCanvas::iconQuadrantFill( double x, double y, Individual *pIndividual ){
	
	//
	// Handle virtual individuals:
	//
	if(pIndividual->isVirtual()){
		
		return;
		
	}
	//
	// Get here if non-virtual:
	//
	
	//
	// How many sections are there?
	//
	unsigned sections = pIndividual->getDataTable()->getIconColumnCount();
	if(!sections){
		//
		// No affected fields : Draw a small circle in the middle:
		// (Nice for debugging -- otherwise comment out )
		//
		//_body << "<circle cx=\"" << x << "\" cy=\"" << y << "\" r=\"" << 0.5*DrawingMetrics::getScalingFactor() << "\"";
		//_body << " class=\"thinLine\"";
		//_body << "/>\n";
		return;
	}
	
	//
	// Setup clipping Id, if needed:
	//
	double radius=DrawingMetrics::getIconRadius();
	bool isMale = false;
	if( pIndividual->getGender().getEnum()==Gender::MALE ){
		
		std::string clipId = pIndividual->getId().get() + "_clipPath";
		setClipPath(x,y,clipId);
		//
		// Increase radius for clipping:
		//
		radius*=Number::SQRT_TWO;
		isMale = true;
		_body << "<g clip-path=\"url(#" << clipId << ")\">\n";
		
	}else{
		//
		// Empty g with no clipping for female:
		//
		_body << "<g>\n";
		
	}
	
	//
	// NOTA BENE: The quadrant fill method looks only at the 
	// FIRST iconColumn and ignores any additional icon columns:
	//
	const DataTable *pDT = pIndividual->getDataTable();
	//
	// Get the data column of the first icon column:
	//
	DataColumn * pDC = pDT->getColumn( pDT->getIconColumnIndex(0) );
	
	//
	// Get the UniqueList for this column:
	//
	const UniqueList * pUL = pDC->getUniqueList();
	//
	// Only process if there are some non-missing levels
	// present:
	//
	if(!pUL->getLevels()){
		_body << "</g>\n";
		return;
	}
	
	//
	// What is the level and label in the UniqueList corresponding to the data value
	// for this individual?
	//
	//unsigned level;
	//std::string label;
	//pUL->getOrdinalAndLabelForKey( pDC->getDataAtIndex( pIndividual->getRowIndex() ),label,level );
	//
	
	Data* data = pDC->getDataAtIndex( pIndividual->getRowIndex());
	//
	// Draw a dot for missing values:
	//
	if(data->isMissing()){
		drawText(x,y,".","blackInkLetter_1");
		_body << "</g>\n";
		return;
	}
	std::string label;
	std::string svalue = data->get();
	std::istringstream i(svalue);
	int level;
	bool converted = (i>>level);
	if(!converted || level<0 || level>15 ){
		//
		// (1) Unable to convert data string to integer, or
		// (2) integer value is out of range
		//
		double lineSpacing,xAdvance,yMinimum,yMaximum;
		_lasiWrapper.getDimensions(svalue,&lineSpacing,&xAdvance,&yMinimum,&yMaximum);
		y+= 0.5*(yMaximum-yMinimum);
		drawIconText(x,y,svalue,"blackInkLetter_1");
		_body << "</g>\n";
		return;
	}
	
	//
	// Fill arc for each quadrant based on level:
	// Note: Madeline's "arc()" method doesn't use the standard counter-clockwise quadrants
	// starting at 0, so the order of the 4 "if" statements below may appear mixed up but 
	// this actually results in shading of the quadrants according to standard notation:
	//
	if(level & 0x02 ){
		arc(x,y,radius,0,0.5*Number::PI,"#000",label,"whiteInkLetter",isMale);
	}
	if(level & 0x01 ){
		arc(x,y,radius,0.5*Number::PI,Number::PI,"#000",label,"whiteInkLetter",isMale);
	}
	if(level & 0x08 ){
		arc(x,y,radius,Number::PI,1.5*Number::PI,"#000",label,"whiteInkLetter",isMale);
	}
	if(level & 0x04 ){
		arc(x,y,radius,1.5*Number::PI,2.0*Number::PI,"#000",label,"whiteInkLetter",isMale);
	}
	
	//
	// For the first time draw the icon legend too:
	//
	//if(!_iconLegendFlag){
	//	_iconLegendFlag = true;
	//	_iconLegend.setPedigreeTable(pDT);
	//}
	
	_body << "</g>\n";
	return;
	
}