- handle color drops as a new style
- handle dropped/pastes text as shapes with path (and style when with text_runs from StyledEdit) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28064 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
249a4a187e
commit
8457f71f08
@ -50,6 +50,7 @@ local sourceDirs =
|
||||
import_export/flat_icon
|
||||
import_export/message
|
||||
import_export/svg
|
||||
import_export/styled_text
|
||||
shape
|
||||
shape/commands
|
||||
style
|
||||
@ -229,6 +230,9 @@ Application Icon-O-Matic :
|
||||
MessageExporter.cpp
|
||||
MessageImporter.cpp
|
||||
|
||||
# import_export/styled_text
|
||||
StyledTextImporter.cpp
|
||||
|
||||
# import_export/svg
|
||||
DocumentBuilder.cpp
|
||||
PathTokenizer.cpp
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Clipboard.h>
|
||||
#include <Menu.h>
|
||||
#include <MenuBar.h>
|
||||
#include <MenuItem.h>
|
||||
@ -63,6 +64,8 @@
|
||||
#include "StyleContainer.h"
|
||||
#include "VectorPath.h"
|
||||
|
||||
#include "StyledTextImporter.h"
|
||||
|
||||
using std::nothrow;
|
||||
|
||||
enum {
|
||||
@ -120,6 +123,24 @@ MainWindow::MessageReceived(BMessage* message)
|
||||
return;
|
||||
}
|
||||
|
||||
if (message->WasDropped()) {
|
||||
const rgb_color *color;
|
||||
int32 len;
|
||||
int32 i;
|
||||
// create styles from dropped colors
|
||||
for (i = 0; message->FindData("RGBColor", B_RGB_COLOR_TYPE, i,
|
||||
(const void **)&color, &len) == B_OK; i++) {
|
||||
if (len != sizeof(rgb_color))
|
||||
continue;
|
||||
Style* style = new (nothrow) Style(*color);
|
||||
Style* styles[1] = { style };
|
||||
AddStylesCommand* styleCommand = new (nothrow) AddStylesCommand(
|
||||
fDocument->Icon()->Styles(), styles, 1,
|
||||
fDocument->Icon()->Styles()->CountStyles());
|
||||
fDocument->CommandStack()->Perform(styleCommand);
|
||||
}
|
||||
}
|
||||
|
||||
switch (message->what) {
|
||||
|
||||
case B_REFS_RECEIVED:
|
||||
@ -130,6 +151,63 @@ MainWindow::MessageReceived(BMessage* message)
|
||||
be_app->PostMessage(message);
|
||||
break;
|
||||
|
||||
case B_MIME_DATA:
|
||||
if (message->HasData("text/plain", B_MIME_TYPE)) {
|
||||
status_t err;
|
||||
Icon* icon;
|
||||
icon = new (nothrow) Icon(*fDocument->Icon());
|
||||
if (icon) {
|
||||
StyledTextImporter importer;
|
||||
err = importer.Import(icon, message);
|
||||
if (err >= B_OK) {
|
||||
AutoWriteLocker locker(fDocument);
|
||||
|
||||
SetIcon(NULL);
|
||||
|
||||
// incorporate the loaded icon into the document
|
||||
// (either replace it or append to it)
|
||||
fDocument->MakeEmpty(false);
|
||||
// if append, the document savers are preserved
|
||||
fDocument->SetIcon(icon);
|
||||
SetIcon(icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case B_PASTE:
|
||||
if (be_clipboard->Lock()) {
|
||||
status_t err;
|
||||
BMessage *clip = be_clipboard->Data();
|
||||
|
||||
if (!clip || !clip->HasData("text/plain", B_MIME_TYPE)) {
|
||||
be_clipboard->Unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
Icon* icon;
|
||||
icon = new (nothrow) Icon(*fDocument->Icon());
|
||||
if (icon) {
|
||||
StyledTextImporter importer;
|
||||
err = importer.Import(icon, clip);
|
||||
if (err >= B_OK) {
|
||||
AutoWriteLocker locker(fDocument);
|
||||
|
||||
SetIcon(NULL);
|
||||
|
||||
// incorporate the loaded icon into the document
|
||||
// (either replace it or append to it)
|
||||
fDocument->MakeEmpty(false);
|
||||
// if append, the document savers are preserved
|
||||
fDocument->SetIcon(icon);
|
||||
SetIcon(icon);
|
||||
}
|
||||
}
|
||||
|
||||
be_clipboard->Unlock();
|
||||
}
|
||||
break;
|
||||
|
||||
case MSG_UNDO:
|
||||
fDocument->CommandStack()->Undo();
|
||||
break;
|
||||
|
@ -0,0 +1,338 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* François Revol <revol@free.fr>
|
||||
*/
|
||||
#include "StyledTextImporter.h"
|
||||
|
||||
#include <new>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Archivable.h>
|
||||
#include <ByteOrder.h>
|
||||
#include <DataIO.h>
|
||||
#include <File.h>
|
||||
#include <List.h>
|
||||
#include <Message.h>
|
||||
#include <NodeInfo.h>
|
||||
#include <Shape.h>
|
||||
#include <String.h>
|
||||
#include <TextView.h>
|
||||
|
||||
#include "Defines.h"
|
||||
#include "Icon.h"
|
||||
#include "PathContainer.h"
|
||||
#include "Shape.h"
|
||||
#include "Style.h"
|
||||
#include "StyleContainer.h"
|
||||
#include "VectorPath.h"
|
||||
|
||||
//#define CALLED() printf("%s()\n", __FUNCTION__);
|
||||
#define CALLED() do {} while (0)
|
||||
|
||||
using std::nothrow;
|
||||
|
||||
class ShapeIterator : public BShapeIterator {
|
||||
public:
|
||||
ShapeIterator(Icon *icon, Shape *to, BPoint offset);
|
||||
~ShapeIterator() {};
|
||||
|
||||
virtual status_t IterateMoveTo(BPoint *point);
|
||||
virtual status_t IterateLineTo(int32 lineCount, BPoint *linePts);
|
||||
virtual status_t IterateBezierTo(int32 bezierCount, BPoint *bezierPts);
|
||||
virtual status_t IterateClose();
|
||||
|
||||
private:
|
||||
VectorPath *CurrentPath();
|
||||
void NextPath();
|
||||
|
||||
Icon *fIcon;
|
||||
Shape *fShape;
|
||||
VectorPath *fPath;
|
||||
BPoint fOffset;
|
||||
};
|
||||
|
||||
ShapeIterator::ShapeIterator(Icon *icon, Shape *to, BPoint offset)
|
||||
{
|
||||
CALLED();
|
||||
fIcon = icon;
|
||||
fShape = to;
|
||||
fPath = NULL;
|
||||
fOffset = offset;
|
||||
}
|
||||
|
||||
status_t
|
||||
ShapeIterator::IterateMoveTo(BPoint *point)
|
||||
{
|
||||
CALLED();
|
||||
if (fPath)
|
||||
NextPath();
|
||||
if (!CurrentPath())
|
||||
return B_ERROR;
|
||||
fPath->AddPoint(fOffset + *point);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
ShapeIterator::IterateLineTo(int32 lineCount, BPoint *linePts)
|
||||
{
|
||||
CALLED();
|
||||
if (!CurrentPath())
|
||||
return B_ERROR;
|
||||
while (lineCount--)
|
||||
fPath->AddPoint(fOffset + *linePts++);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
ShapeIterator::IterateBezierTo(int32 bezierCount, BPoint *bezierPts)
|
||||
{
|
||||
CALLED();
|
||||
if (!CurrentPath())
|
||||
return B_ERROR;
|
||||
while (bezierCount--) {
|
||||
fPath->AddPoint(fOffset + *bezierPts++,
|
||||
fOffset + *bezierPts++, fOffset + *bezierPts++, false);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
ShapeIterator::IterateClose()
|
||||
{
|
||||
CALLED();
|
||||
if (!CurrentPath())
|
||||
return B_ERROR;
|
||||
fPath->SetClosed(true);
|
||||
NextPath();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
VectorPath *
|
||||
ShapeIterator::CurrentPath()
|
||||
{
|
||||
CALLED();
|
||||
if (fPath)
|
||||
return fPath;
|
||||
fPath = new (nothrow) VectorPath();
|
||||
return fPath;
|
||||
}
|
||||
|
||||
void
|
||||
ShapeIterator::NextPath()
|
||||
{
|
||||
CALLED();
|
||||
if (fPath) {
|
||||
fIcon->Paths()->AddPath(fPath);
|
||||
fShape->Paths()->AddPath(fPath);
|
||||
}
|
||||
fPath = NULL;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// constructor
|
||||
StyledTextImporter::StyledTextImporter()
|
||||
: Importer(),
|
||||
fStyleMap(NULL),
|
||||
fStyleCount(0)
|
||||
{
|
||||
CALLED();
|
||||
}
|
||||
|
||||
// destructor
|
||||
StyledTextImporter::~StyledTextImporter()
|
||||
{
|
||||
CALLED();
|
||||
}
|
||||
|
||||
// Import
|
||||
status_t
|
||||
StyledTextImporter::Import(Icon* icon, BMessage* clipping)
|
||||
{
|
||||
CALLED();
|
||||
const char *text;
|
||||
int32 textLength;
|
||||
|
||||
if (clipping == NULL)
|
||||
return ENOENT;
|
||||
if (clipping->FindData("text/plain",
|
||||
B_MIME_TYPE, (const void **)&text, &textLength) == B_OK) {
|
||||
text_run_array *runs = NULL;
|
||||
int32 runsLength;
|
||||
if (clipping->FindData("application/x-vnd.Be-text_run_array",
|
||||
B_MIME_TYPE, (const void **)&runs, &runsLength) < B_OK)
|
||||
runs = NULL;
|
||||
BString str(text, textLength);
|
||||
return _Import(icon, str.String(), runs);
|
||||
}
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
// Import
|
||||
status_t
|
||||
StyledTextImporter::Import(Icon* icon, const entry_ref* ref)
|
||||
{
|
||||
CALLED();
|
||||
status_t err;
|
||||
BFile file(ref, B_READ_ONLY);
|
||||
err = file.InitCheck();
|
||||
if (err < B_OK)
|
||||
return err;
|
||||
|
||||
BNodeInfo info(&file);
|
||||
char mime[B_MIME_TYPE_LENGTH];
|
||||
err = info.GetType(mime);
|
||||
if (err < B_OK)
|
||||
return err;
|
||||
|
||||
if (strncmp(mime, "text/plain", B_MIME_TYPE_LENGTH))
|
||||
return EINVAL;
|
||||
|
||||
off_t size;
|
||||
err = file.GetSize(&size);
|
||||
if (err < B_OK)
|
||||
return err;
|
||||
if (size > UINT32_MAX - 1)
|
||||
return E2BIG;
|
||||
|
||||
BMallocIO mio;
|
||||
mio.SetSize((size_t)size + 1);
|
||||
memset((void *)mio.Buffer(), 0, (size_t)size + 1);
|
||||
|
||||
// TODO: read runs
|
||||
|
||||
return _Import(icon, (const char *)mio.Buffer(), NULL);
|
||||
}
|
||||
|
||||
// _Import
|
||||
status_t
|
||||
StyledTextImporter::_Import(Icon* icon, const char *text, text_run_array *runs)
|
||||
{
|
||||
CALLED();
|
||||
status_t ret = Init(icon);
|
||||
if (ret < B_OK) {
|
||||
printf("StyledTextImporter::Import() - "
|
||||
"Init() error: %s\n", strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
StyleContainer* styles = icon->Styles();
|
||||
// import run colors as styles
|
||||
if (runs) {
|
||||
fStyleMap = new struct style_map[runs->count];
|
||||
for (int32 i = 0; runs && i < runs->count; i++) {
|
||||
_AddStyle(icon, &runs->runs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
int32 currentRun = 0;
|
||||
text_run *run = NULL;
|
||||
if (runs)
|
||||
run = &runs->runs[0];
|
||||
BString str(text);
|
||||
int32 len = str.Length();
|
||||
int32 chars = str.CountChars();
|
||||
BPoint offset(0,0);
|
||||
|
||||
for (int32 i = 0, c = 0; i < len && c < chars; c++) {
|
||||
// make sure we are still on the (good) run
|
||||
while (run && currentRun < runs->count - 1 &&
|
||||
i >= runs->runs[currentRun + 1].offset) {
|
||||
printf("switching to run %d\n", currentRun);
|
||||
run = &runs->runs[++currentRun];
|
||||
}
|
||||
|
||||
BShape glyph;
|
||||
BShape *glyphs[1] = { &glyph };
|
||||
BFont font(be_plain_font);
|
||||
if (run)
|
||||
font = run->font;
|
||||
|
||||
font.GetGlyphShapes((str.String() + i), 1, glyphs);
|
||||
if (glyph.Bounds().IsValid()) {
|
||||
offset.x += glyph.Bounds().Width();
|
||||
Shape* shape = new (nothrow) Shape(NULL);
|
||||
if (!shape || !icon->Shapes()->AddShape(shape)) {
|
||||
delete shape;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
for (int j = 0; run && j < fStyleCount; j++) {
|
||||
if (fStyleMap[j].run == run) {
|
||||
shape->SetStyle(fStyleMap[j].style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ShapeIterator iterator(icon, shape, offset);
|
||||
if (iterator.Iterate(&glyph) < B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
}
|
||||
|
||||
// skip the rest of UTF-8 char bytes
|
||||
for (i++; i < len && str[i] & 0x80; i++);
|
||||
}
|
||||
#endif
|
||||
delete[] fStyleMap;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// _AddStyle
|
||||
status_t
|
||||
StyledTextImporter::_AddStyle(Icon *icon, text_run *run)
|
||||
{
|
||||
CALLED();
|
||||
if (!run)
|
||||
return EINVAL;
|
||||
rgb_color color = run->color;
|
||||
Style* style = new (nothrow) Style(color);
|
||||
if (!style) {
|
||||
delete style;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < fStyleCount; i++) {
|
||||
if (*style == *(fStyleMap[i].style)) {
|
||||
delete style;
|
||||
style = fStyleMap[i].style;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && !icon->Styles()->AddStyle(style)) {
|
||||
delete style;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
fStyleMap[fStyleCount].run = run;
|
||||
fStyleMap[fStyleCount].style = style;
|
||||
fStyleCount++;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// _AddPaths
|
||||
status_t
|
||||
StyledTextImporter::_AddPaths(Icon *icon, BShape *shape)
|
||||
{
|
||||
CALLED();
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// _AddShape
|
||||
status_t
|
||||
StyledTextImporter::_AddShape(Icon *icon, BShape *shape, text_run *run)
|
||||
{
|
||||
CALLED();
|
||||
return B_ERROR;
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* François Revol <revol@free.fr>
|
||||
*/
|
||||
#ifndef STYLED_TEXT_IMPORTER_H
|
||||
#define STYLED_TEXT_IMPORTER_H
|
||||
|
||||
|
||||
#include "Importer.h"
|
||||
|
||||
class BMessage;
|
||||
class BShape;
|
||||
struct text_run;
|
||||
struct text_run_array;
|
||||
|
||||
namespace BPrivate {
|
||||
namespace Icon {
|
||||
class Icon;
|
||||
class Style;
|
||||
class VectorPath;
|
||||
class PathContainer;
|
||||
class ShapeContainer;
|
||||
class StyleContainer;
|
||||
}
|
||||
}
|
||||
|
||||
struct style_map {
|
||||
text_run *run;
|
||||
Style *style;
|
||||
};
|
||||
|
||||
class StyledTextImporter : public Importer {
|
||||
public:
|
||||
StyledTextImporter();
|
||||
virtual ~StyledTextImporter();
|
||||
|
||||
status_t Import(Icon* icon,
|
||||
BMessage* clipping);
|
||||
status_t Import(Icon* icon,
|
||||
const entry_ref* ref);
|
||||
|
||||
private:
|
||||
status_t _Import(Icon* icon, const char *text,
|
||||
text_run_array *runs);
|
||||
|
||||
status_t _AddStyle(Icon *icon, text_run *run);
|
||||
status_t _AddPaths(Icon *icon, BShape *shape);
|
||||
status_t _AddShape(Icon *icon, BShape *shape, text_run *run);
|
||||
|
||||
struct style_map *fStyleMap;
|
||||
int32 fStyleCount;
|
||||
};
|
||||
|
||||
#endif // STYLED_TEXT_IMPORTER_H
|
Loading…
Reference in New Issue
Block a user