예제 #1
0
void QTextOdfWriter::writeFrameFormat(QXmlStreamWriter &writer, QTextFrameFormat format, int formatIndex) const
{
    writer.writeStartElement(styleNS, QString::fromLatin1("style"));
    writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("s%1").arg(formatIndex));
    writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("section"));
    writer.writeEmptyElement(styleNS, QString::fromLatin1("section-properties"));
    if (format.hasProperty(QTextFormat::FrameTopMargin))
        writer.writeAttribute(foNS, QString::fromLatin1("margin-top"), pixelToPoint(qMax(qreal(0.), format.topMargin())) );
    if (format.hasProperty(QTextFormat::FrameBottomMargin))
        writer.writeAttribute(foNS, QString::fromLatin1("margin-bottom"), pixelToPoint(qMax(qreal(0.), format.bottomMargin())) );
    if (format.hasProperty(QTextFormat::FrameLeftMargin))
        writer.writeAttribute(foNS, QString::fromLatin1("margin-left"), pixelToPoint(qMax(qreal(0.), format.leftMargin())) );
    if (format.hasProperty(QTextFormat::FrameRightMargin))
        writer.writeAttribute(foNS, QString::fromLatin1("margin-right"), pixelToPoint(qMax(qreal(0.), format.rightMargin())) );

    writer.writeEndElement(); // style

// TODO consider putting the following properties in a qt-namespace.
// Position   position () const
// qreal   border () const
// QBrush   borderBrush () const
// BorderStyle   borderStyle () const
// qreal   padding () const
// QTextLength   width () const
// QTextLength   height () const
// PageBreakFlags   pageBreakPolicy () const
}
예제 #2
0
void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextFragment &fragment) const
{
    writer.writeStartElement(drawNS, QString::fromLatin1("frame"));
    if (m_strategy == 0) {
        // don't do anything.
    }
    else if (fragment.charFormat().isImageFormat()) {
        QTextImageFormat imageFormat = fragment.charFormat().toImageFormat();
        writer.writeAttribute(drawNS, QString::fromLatin1("name"), imageFormat.name());

        // vvv  Copy pasted mostly from Qt =================
        QImage image;
        QString name = imageFormat.name();
        if (name.startsWith(QLatin1String(":/"))) // auto-detect resources
            name.prepend(QLatin1String("qrc"));
        QUrl url = QUrl::fromEncoded(name.toUtf8());
        const QVariant data = m_document->resource(QTextDocument::ImageResource, url);
        if (data.type() == QVariant::Image) {
            image = qvariant_cast<QImage>(data);
        } else if (data.type() == QVariant::ByteArray) {
            image.loadFromData(data.toByteArray());
        }

        if (image.isNull()) {
            QString context;
            if (QTextImageHandler::externalLoader)
                image = QTextImageHandler::externalLoader(name, context);

            if (image.isNull()) { // try direct loading
                name = imageFormat.name(); // remove qrc:/ prefix again
                image.load(name);
            }
        }

        // ^^^ Copy pasted mostly from Qt =================
        if (! image.isNull()) {
            QBuffer imageBytes;
            QImageWriter imageWriter(&imageBytes, "png");
            imageWriter.write(image);
            QString filename = m_strategy->createUniqueImageName();
            m_strategy->addFile(filename, QString::fromLatin1("image/png"), imageBytes.data());

            // get the width/height from the format.
            qreal width = (imageFormat.hasProperty(QTextFormat::ImageWidth)) ? imageFormat.width() : image.width();
            writer.writeAttribute(svgNS, QString::fromLatin1("width"), pixelToPoint(width));
            qreal height = (imageFormat.hasProperty(QTextFormat::ImageHeight)) ? imageFormat.height() : image.height();
            writer.writeAttribute(svgNS, QString::fromLatin1("height"), pixelToPoint(height));

            writer.writeStartElement(drawNS, QString::fromLatin1("image"));
            writer.writeAttribute(xlinkNS, QString::fromLatin1("href"), filename);
            writer.writeEndElement(); // image
        }
    }

    writer.writeEndElement(); // frame
}
예제 #3
0
void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCellFormat format, int formatIndex) const
{
    writer.writeStartElement(styleNS, QString::fromLatin1("style"));
    writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("T%1").arg(formatIndex));
    writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("table"));
    writer.writeEmptyElement(styleNS, QString::fromLatin1("table-properties"));


    qreal padding = format.topPadding();
    if (padding > 0 && padding == format.bottomPadding()
        && padding == format.leftPadding() && padding == format.rightPadding()) {
        writer.writeAttribute(foNS, QString::fromLatin1("padding"), pixelToPoint(padding));
    }
    else {
        if (padding > 0)
            writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(padding));
        if (format.bottomPadding() > 0)
            writer.writeAttribute(foNS, QString::fromLatin1("padding-bottom"), pixelToPoint(format.bottomPadding()));
        if (format.leftPadding() > 0)
            writer.writeAttribute(foNS, QString::fromLatin1("padding-left"), pixelToPoint(format.leftPadding()));
        if (format.rightPadding() > 0)
            writer.writeAttribute(foNS, QString::fromLatin1("padding-right"), pixelToPoint(format.rightPadding()));
    }

    if (format.hasProperty(QTextFormat::TextVerticalAlignment)) {
        QString pos;
        switch (format.verticalAlignment()) {
        case QTextCharFormat::AlignMiddle:
            pos = QString::fromLatin1("middle"); break;
        case QTextCharFormat::AlignTop:
            pos = QString::fromLatin1("top"); break;
        case QTextCharFormat::AlignBottom:
            pos = QString::fromLatin1("bottom"); break;
        default:
            pos = QString::fromLatin1("automatic"); break;
        }
        writer.writeAttribute(styleNS, QString::fromLatin1("vertical-align"), pos);
    }

    // TODO
    // ODF just search for style-table-cell-properties-attlist)
    // QTextFormat::BackgroundImageUrl
    // format.background
    // QTextFormat::FrameBorder

    writer.writeEndElement(); // style
}
예제 #4
0
void QTextOdfWriter::writeCharacterFormat(QXmlStreamWriter &writer, QTextCharFormat format, int formatIndex) const
{
    writer.writeStartElement(styleNS, QString::fromLatin1("style"));
    writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("c%1").arg(formatIndex));
    writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("text"));
    writer.writeEmptyElement(styleNS, QString::fromLatin1("text-properties"));
    if (format.fontItalic())
        writer.writeAttribute(foNS, QString::fromLatin1("font-style"), QString::fromLatin1("italic"));
    if (format.hasProperty(QTextFormat::FontWeight) && format.fontWeight() != QFont::Normal) {
        QString value;
        if (format.fontWeight() == QFont::Bold)
            value = QString::fromLatin1("bold");
        else
            value = QString::number(format.fontWeight() * 10);
        writer.writeAttribute(foNS, QString::fromLatin1("font-weight"), value);
    }
    if (format.hasProperty(QTextFormat::FontFamily))
        writer.writeAttribute(foNS, QString::fromLatin1("font-family"), format.fontFamily());
    else
        writer.writeAttribute(foNS, QString::fromLatin1("font-family"), QString::fromLatin1("Sans")); // Qt default
    if (format.hasProperty(QTextFormat::FontPointSize))
        writer.writeAttribute(foNS, QString::fromLatin1("font-size"), QString::fromLatin1("%1pt").arg(format.fontPointSize()));
    if (format.hasProperty(QTextFormat::FontCapitalization)) {
        switch(format.fontCapitalization()) {
        case QFont::MixedCase:
            writer.writeAttribute(foNS, QString::fromLatin1("text-transform"), QString::fromLatin1("none")); break;
        case QFont::AllUppercase:
            writer.writeAttribute(foNS, QString::fromLatin1("text-transform"), QString::fromLatin1("uppercase")); break;
        case QFont::AllLowercase:
            writer.writeAttribute(foNS, QString::fromLatin1("text-transform"), QString::fromLatin1("lowercase")); break;
        case QFont::Capitalize:
            writer.writeAttribute(foNS, QString::fromLatin1("text-transform"), QString::fromLatin1("capitalize")); break;
        case QFont::SmallCaps:
            writer.writeAttribute(foNS, QString::fromLatin1("font-variant"), QString::fromLatin1("small-caps")); break;
        }
    }
    if (format.hasProperty(QTextFormat::FontLetterSpacing))
        writer.writeAttribute(foNS, QString::fromLatin1("letter-spacing"), pixelToPoint(format.fontLetterSpacing()));
    if (format.hasProperty(QTextFormat::FontWordSpacing) && format.fontWordSpacing() != 0)
            writer.writeAttribute(foNS, QString::fromLatin1("word-spacing"), pixelToPoint(format.fontWordSpacing()));
    if (format.hasProperty(QTextFormat::FontUnderline))
        writer.writeAttribute(styleNS, QString::fromLatin1("text-underline-type"),
                format.fontUnderline() ? QString::fromLatin1("single") : QString::fromLatin1("none"));
    if (format.hasProperty(QTextFormat::FontOverline)) {
        //   bool   fontOverline () const  TODO
    }
    if (format.hasProperty(QTextFormat::FontStrikeOut))
        writer.writeAttribute(styleNS,QString::fromLatin1( "text-line-through-type"),
                format.fontStrikeOut() ? QString::fromLatin1("single") : QString::fromLatin1("none"));
    if (format.hasProperty(QTextFormat::TextUnderlineColor))
        writer.writeAttribute(styleNS, QString::fromLatin1("text-underline-color"), format.underlineColor().name());
    if (format.hasProperty(QTextFormat::FontFixedPitch)) {
        //   bool   fontFixedPitch () const  TODO
    }
    if (format.hasProperty(QTextFormat::TextUnderlineStyle)) {
        QString value;
        switch (format.underlineStyle()) {
        case QTextCharFormat::NoUnderline: value = QString::fromLatin1("none"); break;
        case QTextCharFormat::SingleUnderline: value = QString::fromLatin1("solid"); break;
        case QTextCharFormat::DashUnderline: value = QString::fromLatin1("dash"); break;
        case QTextCharFormat::DotLine: value = QString::fromLatin1("dotted"); break;
        case QTextCharFormat::DashDotLine: value = QString::fromLatin1("dash-dot"); break;
        case QTextCharFormat::DashDotDotLine: value = QString::fromLatin1("dot-dot-dash"); break;
        case QTextCharFormat::WaveUnderline: value = QString::fromLatin1("wave"); break;
        case QTextCharFormat::SpellCheckUnderline: value = QString::fromLatin1("none"); break;
        }
        writer.writeAttribute(styleNS, QString::fromLatin1("text-underline-style"), value);
    }
    if (format.hasProperty(QTextFormat::TextVerticalAlignment)) {
        QString value;
        switch (format.verticalAlignment()) {
        case QTextCharFormat::AlignMiddle:
        case QTextCharFormat::AlignNormal: value = QString::fromLatin1("0%"); break;
        case QTextCharFormat::AlignSuperScript: value = QString::fromLatin1("super"); break;
        case QTextCharFormat::AlignSubScript: value = QString::fromLatin1("sub"); break;
        case QTextCharFormat::AlignTop: value = QString::fromLatin1("100%"); break;
        case QTextCharFormat::AlignBottom : value = QString::fromLatin1("-100%"); break;
        case QTextCharFormat::AlignBaseline: break;
        }
        writer.writeAttribute(styleNS, QString::fromLatin1("text-position"), value);
    }
    if (format.hasProperty(QTextFormat::TextOutline))
        writer.writeAttribute(styleNS, QString::fromLatin1("text-outline"), QString::fromLatin1("true"));
    if (format.hasProperty(QTextFormat::TextToolTip)) {
        //   QString   toolTip () const  TODO
    }
    if (format.hasProperty(QTextFormat::IsAnchor)) {
        //   bool   isAnchor () const  TODO
    }
    if (format.hasProperty(QTextFormat::AnchorHref)) {
        //   QString   anchorHref () const  TODO
    }
    if (format.hasProperty(QTextFormat::AnchorName)) {
        //   QString   anchorName () const  TODO
    }
    if (format.hasProperty(QTextFormat::ForegroundBrush)) {
        QBrush brush = format.foreground();
        writer.writeAttribute(foNS, QString::fromLatin1("color"), brush.color().name());
    }
    if (format.hasProperty(QTextFormat::BackgroundBrush)) {
        QBrush brush = format.background();
        writer.writeAttribute(foNS, QString::fromLatin1("background-color"), brush.color().name());
    }

    writer.writeEndElement(); // style
}
예제 #5
0
void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat format, int formatIndex) const
{
    writer.writeStartElement(styleNS, QString::fromLatin1("style"));
    writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("p%1").arg(formatIndex));
    writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("paragraph"));
    writer.writeStartElement(styleNS, QString::fromLatin1("paragraph-properties"));

    if (format.hasProperty(QTextFormat::BlockAlignment)) {
        const Qt::Alignment alignment = format.alignment() & Qt::AlignHorizontal_Mask;
        QString value;
        if (alignment == Qt::AlignLeading)
            value = QString::fromLatin1("start");
        else if (alignment == Qt::AlignTrailing)
            value = QString::fromLatin1("end");
        else if (alignment == (Qt::AlignLeft | Qt::AlignAbsolute))
            value = QString::fromLatin1("left");
        else if (alignment == (Qt::AlignRight | Qt::AlignAbsolute))
            value = QString::fromLatin1("right");
        else if (alignment == Qt::AlignHCenter)
            value = QString::fromLatin1("center");
        else if (alignment == Qt::AlignJustify)
            value = QString::fromLatin1("justify");
        else
            qWarning() << "QTextOdfWriter: unsupported paragraph alignment; " << format.alignment();
        if (! value.isNull())
            writer.writeAttribute(foNS, QString::fromLatin1("text-align"), value);
    }

    if (format.hasProperty(QTextFormat::BlockTopMargin))
        writer.writeAttribute(foNS, QString::fromLatin1("margin-top"), pixelToPoint(qMax(qreal(0.), format.topMargin())) );
    if (format.hasProperty(QTextFormat::BlockBottomMargin))
        writer.writeAttribute(foNS, QString::fromLatin1("margin-bottom"), pixelToPoint(qMax(qreal(0.), format.bottomMargin())) );
    if (format.hasProperty(QTextFormat::BlockLeftMargin) || format.hasProperty(QTextFormat::BlockIndent))
        writer.writeAttribute(foNS, QString::fromLatin1("margin-left"), pixelToPoint(qMax(qreal(0.),
            format.leftMargin() + format.indent())));
    if (format.hasProperty(QTextFormat::BlockRightMargin))
        writer.writeAttribute(foNS, QString::fromLatin1("margin-right"), pixelToPoint(qMax(qreal(0.), format.rightMargin())) );
    if (format.hasProperty(QTextFormat::TextIndent))
        writer.writeAttribute(foNS, QString::fromLatin1("text-indent"), pixelToPoint(format.textIndent()));
    if (format.hasProperty(QTextFormat::PageBreakPolicy)) {
        if (format.pageBreakPolicy() & QTextFormat::PageBreak_AlwaysBefore)
            writer.writeAttribute(foNS, QString::fromLatin1("break-before"), QString::fromLatin1("page"));
        if (format.pageBreakPolicy() & QTextFormat::PageBreak_AlwaysAfter)
            writer.writeAttribute(foNS, QString::fromLatin1("break-after"), QString::fromLatin1("page"));
    }
    if (format.hasProperty(QTextFormat::BackgroundBrush)) {
        QBrush brush = format.background();
        writer.writeAttribute(foNS, QString::fromLatin1("background-color"), brush.color().name());
    }
    if (format.hasProperty(QTextFormat::BlockNonBreakableLines))
        writer.writeAttribute(foNS, QString::fromLatin1("keep-together"),
                format.nonBreakableLines() ? QString::fromLatin1("true") : QString::fromLatin1("false"));
    if (format.hasProperty(QTextFormat::TabPositions)) {
        QList<QTextOption::Tab> tabs = format.tabPositions();
        writer.writeStartElement(styleNS, QString::fromLatin1("tab-stops"));
        QList<QTextOption::Tab>::Iterator iterator = tabs.begin();
        while(iterator != tabs.end()) {
            writer.writeEmptyElement(styleNS, QString::fromLatin1("tab-stop"));
            writer.writeAttribute(styleNS, QString::fromLatin1("position"), pixelToPoint(iterator->position) );
            QString type;
            switch(iterator->type) {
            case QTextOption::DelimiterTab: type = QString::fromLatin1("char"); break;
            case QTextOption::LeftTab: type = QString::fromLatin1("left"); break;
            case QTextOption::RightTab: type = QString::fromLatin1("right"); break;
            case QTextOption::CenterTab: type = QString::fromLatin1("center"); break;
            }
            writer.writeAttribute(styleNS, QString::fromLatin1("type"), type);
            if (iterator->delimiter != 0)
                writer.writeAttribute(styleNS, QString::fromLatin1("char"), iterator->delimiter);
            ++iterator;
        }

        writer.writeEndElement(); // tab-stops
    }

    writer.writeEndElement(); // paragraph-properties
    writer.writeEndElement(); // style
}
예제 #6
0
 float rowPointSize(ROW *row,int resolution)
 {
     float ptsize = pixelToPoint(rowPixelSize(row), resolution);
     return ptsize;
 }
예제 #7
0
void updateEditor(SDL_Event event, EditorData* data)
{
	
	GUI_sendEventToGUI(data->gui, &event);

	const unsigned char* keyboardState = SDL_GetKeyboardState(NULL);
	int2 mousePixel;
	SDL_GetMouseState(&mousePixel.x, &mousePixel.y);

	float2 mousePos = pixelToPoint(&data->view, mousePixel);


	updateBones(data);

	switch (event.type)
	{
	case SDL_KEYDOWN:
	{

		switch (event.key.keysym.scancode)
		{
		case SDL_SCANCODE_S:
			if (event.key.keysym.mod == KMOD_LCTRL)
			{
				SDL_Event lastEvent = data->lowEventStack.Top();

				if (lastEvent.key.keysym.scancode == SDL_SCANCODE_S && lastEvent.key.keysym.mod == KMOD_LCTRL)
				{
					// save skeleton

					GUI_WidgetID widget = GUI_addContainer(data->gui, GUI_MAIN_WIDGET, { 400 - 100, 300 - 25, 200, 50}, GUI_Container::Orientation::HORIZONTAL);

					auto callbackSave = [](GUI* gui, GUI_WidgetID widgetID, void* editorData)
					{
						EditorData* data = (EditorData*)editorData;

						GUI_WidgetID widget = GUI_getParentWidget(gui, widgetID);

						const char* filename = GUI_getTextfield(gui, GUI_getChildWidget(gui, widget, 0)).text;

						saveSkeleton(filename, &data->skeleton[0], &data->names[0], data->skeleton.size());

						GUI_removeWidget(gui, widget);
					};

					auto callbackCancel = [](GUI* gui, GUI_WidgetID widgetID, void*)
					{
						GUI_WidgetID widget = GUI_getParentWidget(gui, widgetID);
						GUI_removeWidget(gui, widget);
					};

					GUI_addTextfield(data->gui, widget, { 0, 0, -1, -1 }, "filename");
					GUI_addButton(data->gui, widget, { 0, 0, 50, -1 }, "Save", data, callbackSave);
					GUI_addButton(data->gui, widget, { 0, 0, 50, -1 }, "Cancel", 0, callbackCancel);

					break;
				}
				else if (lastEvent.key.keysym.scancode == SDL_SCANCODE_O && lastEvent.key.keysym.mod == KMOD_LCTRL)
				{
					// load skeleton

					GUI_WidgetID widget = GUI_addContainer(data->gui, GUI_MAIN_WIDGET, { 400 - 100, 300 - 15, 200, 30 }, GUI_Container::Orientation::HORIZONTAL);


					auto callbackLoad = [](GUI* gui, GUI_WidgetID widgetID, void* editorData)
					{
						EditorData* data = (EditorData*)editorData;

						GUI_WidgetID widget = GUI_getParentWidget(gui, widgetID);

						const char* filename = GUI_getTextfield(gui, GUI_getChildWidget(gui, widget, 0)).text;

						strcpy(data->skeletonName, filename);
						
						const SkeletonSave* save = loadSkeleton(filename);

						if (save != 0)
						{
							data->bones.clear();
							data->skeleton.clear();
							data->constraints.clear();
							data->names.clear();

							const char* name = save->names;
							for (int i = 0; i < save->numBones; ++i)
							{
								Bone newBone;
								newBone.jointAngle = { 1, 0 };
								newBone.jointPos = save->jointPos[i];
								newBone.parentJoint = save->parentJoints[i];
								newBone.name = data->names.push({ { 0 } });

								memcpy(data->names[newBone.name].string, name, save->nameLen[i] * sizeof(char));
								name += save->nameLen[i];

								Constraint constraint;
								constraint.minAngle = -PI;
								constraint.maxAngle = 3 * PI;

								data->skeleton.push(newBone);
								data->constraints.push(constraint);
							}

							updateBones(data);
						}

						GUI_removeWidget(gui, widget);
					};

					auto callbackCancel = [](GUI* gui, GUI_WidgetID widgetID, void*)
					{
						GUI_WidgetID widget = GUI_getParentWidget(gui, widgetID);
						GUI_removeWidget(gui, widget);
					};

					GUI_addTextfield(data->gui, widget, { 0, 0, -1, -1 }, "filename");
					GUI_addButton(data->gui, widget, { 0, 0, 50, -1 }, "Load", data, callbackLoad);
					GUI_addButton(data->gui, widget, { 0, 0, 50, -1 }, "Cancel", 0, callbackCancel);



					break;
				}


				data->lowEventStack.Push(event);
			}


			break;
			case SDL_SCANCODE_K:
				if (event.key.keysym.mod == KMOD_LCTRL)
				{
					SDL_Event lastEvent = data->lowEventStack.Top();

					if (lastEvent.key.keysym.scancode == SDL_SCANCODE_S && lastEvent.key.keysym.mod == KMOD_LCTRL)
					{
						// save keyFrame

						GUI_WidgetID widget = GUI_addContainer(data->gui, GUI_MAIN_WIDGET, { 400 - 100, 300 - 15, 200, 30 }, GUI_Container::Orientation::HORIZONTAL);

						auto callbackSave = [](GUI* gui, GUI_WidgetID widgetID, void* editorData)
						{
							EditorData* data = (EditorData*)editorData;

							GUI_WidgetID widget = GUI_getParentWidget(gui, widgetID);

							const char* filename = GUI_getTextfield(gui, GUI_getChildWidget(gui, widget, 0)).text;

							saveKeyFrame(filename, &data->skeleton[0], &data->names[0], data->skeleton.size());

							GUI_removeWidget(gui, widget);
						};

						auto callbackCancel = [](GUI* gui, GUI_WidgetID widgetID, void*)
						{
							GUI_WidgetID widget = GUI_getParentWidget(gui, widgetID);
							GUI_removeWidget(gui, widget);
						};

						GUI_addTextfield(data->gui, widget, { 0, 0, -1, -1 }, "filename");
						GUI_addButton(data->gui, widget, { 0, 0, 50, -1 }, "Save", data, callbackSave);
						GUI_addButton(data->gui, widget, { 0, 0, 50, -1 }, "Cancel", 0, callbackCancel);

						break;
					}
					else if (lastEvent.key.keysym.scancode == SDL_SCANCODE_O && lastEvent.key.keysym.mod == KMOD_LCTRL)
					{
						// load keyframe

						GUI_WidgetID widget = GUI_addContainer(data->gui, GUI_MAIN_WIDGET, { 400 - 100, 300 - 15, 200, 30 }, GUI_Container::Orientation::HORIZONTAL);


						auto callbackLoad = [](GUI* gui, GUI_WidgetID widgetID, void* editorData)
						{
							EditorData* data = (EditorData*)editorData;

							GUI_WidgetID widget = GUI_getParentWidget(gui, widgetID);

							const char* filename = GUI_getTextfield(gui, GUI_getChildWidget(gui, widget, 0)).text;

							strcpy(data->frameName, filename);

							const KeyFrameSave* save = loadKeyFrame(filename);

							if (save != 0)
							{

								const char* name = save->names;
								for (int i = 0; i < save->numBones; ++i)
								{
									int nameID = -1;
									for (int j = 0; j < data->names.size(); ++j)
									{
										if (strncmp(name, data->names[j].string, save->nameLen[i]) == 0)
										{
											nameID = j;
											break;
										}
									}

									if (nameID != -1)
									{

										if (data->skeleton[nameID].name == nameID)
										{
											data->skeleton[nameID].jointAngle = save->jointAngles[i];
										}
										else
										{
											for (int j = 0; j < data->skeleton.size(); j++)
											{
												if (data->skeleton[j].name = nameID)
													data->skeleton[j].jointAngle = save->jointAngles[i];
											}
										}
									}

									name += save->nameLen[i];
								}

								updateBones(data);
							}

							GUI_removeWidget(gui, widget);
						};

						auto callbackCancel = [](GUI* gui, GUI_WidgetID widgetID, void*)
						{
							GUI_WidgetID widget = GUI_getParentWidget(gui, widgetID);
							GUI_removeWidget(gui, widget);
						};

						GUI_addTextfield(data->gui, widget, { 0, 0, -1, -1 }, "filename");
						GUI_addButton(data->gui, widget, { 0, 0, 50, -1 }, "Load", data, callbackLoad);
						GUI_addButton(data->gui, widget, { 0, 0, 50, -1 }, "Cancel", 0, callbackCancel);


						break;
					}


					data->lowEventStack.Push(event);
				}


				break;
		default:
			data->lowEventStack.Push(event);
			break;

		}
		break;
	}
	case SDL_MOUSEBUTTONDOWN:
	{
		data->newBone = -1;

		if (keyboardState[SDL_SCANCODE_A])
		{
			for (int i = 0; i < data->bones.size(); ++i)
			{
				if (pointInRect(mousePos, data->bones[i].rect))
				{
					int name = data->names.push({ "test" });

					Bone newBone;
					newBone.jointAngle = { 1, 0 };
					newBone.jointPos = { 0, 0 };
					newBone.parentJoint = i;
					newBone.name = name;

					Constraint constraint;
					constraint.minAngle = -PI;
					constraint.maxAngle = 3 * PI;

					int newBoneID = data->skeleton.push(newBone);
					data->constraints.push(constraint);

					int* ids = new int[data->skeleton.size()];

					sortSkeleton(&data->skeleton[0], data->skeleton.size(), ids);

					Constraint* tempConstraints = new Constraint[data->constraints.size()];
					memcpy(tempConstraints, &data->constraints[0], sizeof(Constraint) * data->constraints.size());

					for (int i = 0; i < data->constraints.size(); ++i)
					{
						data->constraints[i] = tempConstraints[ids[i]];
					}

					delete[] tempConstraints;

					//find bone again
					data->newBone = ids[newBoneID];

					// rebuild bone selection

					updateBones(data);

					delete[]ids;


					break;
				}



			}
		}
		else if (keyboardState[SDL_SCANCODE_N])
		{

			for (int i = 0; i < data->bones.size(); ++i)
			{
				if (pointInRect(mousePos, data->bones[i].rect))
				{
					
					int2 pos = pointToPixel(&data->view, float2{ data->bones[i].rect.x + 10, data->bones[i].rect.y });
					
					GUI_WidgetID widget = GUI_addContainer(data->gui, GUI_MAIN_WIDGET, intRect{ pos.x, pos.y, 100, 30 }, GUI_Container::HORIZONTAL);

					struct Args
					{
						EditorData* data;
						int boneId;
					}*args = new Args{ data, i };
						

					auto callbackOk = [](GUI* gui, GUI_WidgetID widgetID, void* args)
					{
						EditorData* data = ((Args*)args)->data;
						int boneID = ((Args*)args)->boneId;

						GUI_WidgetID parentID = GUI_getParentWidget(gui, widgetID);

						const char* newName = GUI_getTextfield(gui, GUI_getChildWidget(gui, parentID, 0)).text;

						strcpy(data->names[data->skeleton[boneID].name].string, newName);

						GUI_removeWidget(gui, parentID);

						delete args;
					};

					GUI_addTextfield(data->gui, widget, intRect{ 0, 0, -1, -1 }, data->names[data->skeleton[i].name].string);
					GUI_addButton(data->gui, widget, intRect{ 0, 0, 30, -1 }, "OK", args, callbackOk);

					break;
				}
			}
		}
		else
		{



			for (int i = 0; i < data->bones.size(); i++)
			{
				if (pointInRect(mousePos, data->bones[i].rect))
				{
					data->selectedBones.push(i);
					data->grabbedBone = i;
				}
			}

			if (data->grabbedBone == -1 && !keyboardState[SDL_SCANCODE_LCTRL])
				data->selectedBones.clear();
		}

		break;
	}
	case SDL_MOUSEBUTTONUP:
	{

		data->grabbedBone = -1;
		break;
	}
	case SDL_MOUSEMOTION:
	{

		

		if (SDL_GetMouseState(0, 0) == SDL_BUTTON_MIDDLE)
		{
			data->view.position.x -= (event.motion.xrel / data->view.scale.x);
			data->view.position.y -= (event.motion.yrel / data->view.scale.y);

		}
		else
		{

			float2 motion = rotate({ (float)event.motion.xrel, (float)event.motion.yrel }, data->view.angle) * float2{ 1 / data->view.scale.x, 1 / data->view.scale.y };

			if (data->newBone != -1)
			{
				float2 angle = getBoneWorldTransform(&data->skeleton[0], data->skeleton.size(), data->newBone).angle;

				float2 rel = rotate(float2{ motion.x, motion.y }, negateRotation(angle));

				data->skeleton[data->newBone].jointPos += rel;
			}


			if (data->grabbedBone != -1)
			{
				if (keyboardState[SDL_SCANCODE_LCTRL])
				{
					float2 angle = getBoneWorldTransform(&data->skeleton[0], data->skeleton.size(), data->skeleton[data->grabbedBone].parentJoint).angle;

					float2 rel = rotate(float2{ motion.x, motion.y }, negateRotation(angle));

					data->skeleton[data->grabbedBone].jointPos += rel;
				}
				else
				{
					animateCCDIKSelection(&data->skeleton[0], &data->constraints[0], data->skeleton.size(),
						&data->selectedBones[0], data->selectedBones.size(), data->grabbedBone, mousePos - float2{ 400, 300 });
				}
			}

		}

		break;
	}
	case SDL_MOUSEWHEEL:
	{
		data->view.scale.x += event.wheel.y*0.1f;
		data->view.scale.y += event.wheel.y*0.1f;

		break;
	}
	}


	
}