ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 DragDrop Layers between TImageEnFolderMView and TImageEnView in both directions
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

PeterPanino

933 Posts

Posted - May 13 2023 :  14:01:39  Show Profile  Reply
I needed to Drag/Drop Layers between a User-Collection of Layers and TImageEnView. Unfortunately, there is no built-in functionality to achieve this. So I implemented the functionality myself - see the attached project:

attach/PeterPanino/2023513135922_DragDropBetweenImageEnMViewAndImageEnView.zip
135.47 KB



Can this project be simplified and/or optimized?

PeterPanino

933 Posts

Posted - May 14 2023 :  05:25:39  Show Profile  Reply
I've added some substantial improvements:
attach/PeterPanino/202351452514_DragDropLayersBetweenImageEnMViewAndImageEnView_v2.zip
147.92 KB

This description summarizes the process I have used in this project: To reach a simple goal, you often must follow winding paths. In this case, the task was to create a persistent collection of layers from which one can drag individual layers onto a canvas surface and insert individual layers created on the canvas back into the layer collection. Unfortunately, it is impossible to save individual layers as single files because layers are always embedded in a background image. When saving layers in the collection, I gave the respective background image of a layer a unique name after cropping the background image to the size of the layer so that it is then not visible in the collection. This trick then serves to identify the background image of the saved layer by this name when the layer is inserted on the canvas and then the background image is removed automatically. So the transferred layer appears individually without a background image on the canvas. For the user, this creates the impression that only the layers are saved in the collection, and then only the layers are transferred to the canvas. The fact that the user does not notice the automatic processes in the background gives him the impression of a simple process, although it is considerably complex in the background.
Go to Top of Page

xequte

38615 Posts

Posted - May 14 2023 :  23:14:12  Show Profile  Reply
Hi Peter

Yes, the project seems to do as advertised. There's not much I can suggest for improvement. The only thing would be that if you only want to save the layer, without the background image, you can set IEN_StoreBackground := False.

// Save the selected layer as a file (that can be imported into other layer sets)
tempView := TImageEnView.Create(nil);
try
  tempView.LayersAdd(ImageEnView1.CurrentLayer);
  tempView.IO.Params.IEN_StoreBackground := False;
  tempView.IO.SaveToFileIEN( SelLayerFilename );
finally
  tempView.Free;
end;


Nigel
Xequte Software
www.imageen.com
Go to Top of Page

PeterPanino

933 Posts

Posted - May 15 2023 :  02:38:38  Show Profile  Reply
Hi Nigel,

Thank you for the hint. However, there is a strange side-effect when using IEN_StoreBackground := False:

This is the Test Layer I need to save:



And this is the code where I save the test layer:

procedure TForm1.ButtonAddSelectedLayerAsClick(Sender: TObject);
// save the Layer in the Exe folder
begin
  var LValue: string := '';
  var LFileExists: Boolean;
  repeat
    if not InputQuery('Add selected Layer to the Collection', 'Layer Name:', LValue) then EXIT;
    // Todo: also validate valid chars, existing file
    LFileExists := FileExists(GetLayerFilePath(LValue));
    CodeSite.Send('TForm1.ButtonAddSelectedLayerAsClick: LFileExists', LFileExists);
  until Trim(LValue) <> '';

  var TempIEV := TImageEnView.Create(nil);
  try
    // copy the Layer selected from ImageEnView1 to TempIEV:
    var idx := TempIEV.LayersAdd(ImageEnView1.CurrentLayer);

    TempIEV.IO.Params.IEN_StoreBackground := False; // do not save the background Layer
    //TempIEV.LayersCropBackground();
    TempIEV.Layers[idx].Name := LValue;             // set the name of the new Layer
    var LFile := GetLayerFilePath(LValue);          // determine the file path
    TempIEV.IO.SaveToFileIEN(LFile);                // save the Layer file
    ImageEnFolderMView1.RefreshFileList;            // refresh the collection view
  finally
    TempIEV.Free;
  end;
end;

function TForm1.GetLayerFilePath(const ALayerName: string): string;
begin
  Result := IncludeTrailingPathDelimiter(FExeFolder) + ALayerName + '.ien';
end;


And this is how the saved test layer looks in the TImageEnFolderMView:



You can see that this looks like the image background is still there (although IEN_StoreBackground = False)!

But when I still crop the background:

TempIEV.LayersCropBackground();


...then the saved Layer does not show the background (which is what I need to achieve):



So why is the background still shown in the TImageEnFolderMView, although IEN_StoreBackground = False?
Go to Top of Page

PeterPanino

933 Posts

Posted - May 15 2023 :  04:53:39  Show Profile  Reply
The background layer seems to be saved anyway, despite IEN_StoreBackground = False. However this option saves me from having to remove the background layer when dropping the layer on ImageEnView1, and thus reduces the complexity of the code.

Here is the improved code with added file-name validation:

function PAIsFilenameValid(const AFilename: string; var errorchar: Char): Boolean;
begin
  Result := True;

  for var i := 1 to Length(AFilename) do
  begin
    if not System.IOUtils.TPath.IsValidFileNameChar(AFilename[i]) then
    begin
      errorchar := AFilename[i];
      Result := False;
      BREAK;
    end;
  end;
end;

procedure TForm1.ButtonAddSelectedLayerAsClick(Sender: TObject);
// save the Layer in the Exe folder
begin
  var LValue: string := '';
  var LFileExists: Boolean;
  var LSaveOK: Boolean := True;
  var IsFileNameValid: Boolean;
  var C: Char;
  repeat
    if not InputQuery('Add selected Layer to the Collection', 'Layer Name:', LValue) then EXIT;

    IsFileNameValid := PAIsFilenameValid(LValue, C);
    if not IsFileNameValid then
    begin
      Application.MessageBox(PChar('This character is not allowed in file-names: ' + C),
        PChar('Application'), MB_OK + MB_ICONINFORMATION + MB_DEFBUTTON2 + MB_TOPMOST);
    end;

    LFileExists := FileExists(GetLayerFilePath(LValue));
    if LFileExists then
    begin
      case
        Application.MessageBox('This file already exists. Do you want to save anyway?',
          PChar('Application'), MB_OKCANCEL + MB_ICONQUESTION + MB_DEFBUTTON2 + MB_TOPMOST)
        of
        IDOK: LSaveOK := True;
        IDCANCEL: LSaveOK := False;
      end;
    end;
  until (Trim(LValue) <> '') and LSaveOK and IsFileNameValid;

  var TempIEV := TImageEnView.Create(nil);
  try
    // copy the Layer selected from ImageEnView1 to TempIEV:
    var idx := TempIEV.LayersAdd(ImageEnView1.CurrentLayer);

    TempIEV.IO.Params.IEN_StoreBackground := False; // do not save the background Layer
    TempIEV.LayersCropBackground(); // the background still needs to be cropped because it is still present in the saved file!
    TempIEV.Layers[idx].Name := LValue;             // set the name of the new Layer
    var LFile := GetLayerFilePath(LValue);          // determine the file path
    TempIEV.IO.SaveToFileIEN(LFile);                // save the Layer file
    ImageEnFolderMView1.RefreshFileList;            // refresh the collection view
  finally
    TempIEV.Free;
  end;
end;

function TForm1.GetLayerFilePath(const ALayerName: string): string;
begin
  Result := IncludeTrailingPathDelimiter(FExeFolder) + ALayerName + '.ien';
end;
Go to Top of Page

xequte

38615 Posts

Posted - May 18 2023 :  00:22:08  Show Profile  Reply
Hi Peter

IEN_StoreBackground is a special case in that the layer position is stored (rather than being centered) to ensure it can be loaded at the same position.

That means it does not preview well.

If you want to center the saved layer, code it as follows:

// Save the selected layer as a file (that can be imported into other layer sets)
tempView := TImageEnView.Create(nil);
try
  tempView.LayersAdd(ImageEnView1.CurrentLayer);
  // Reset layer position to ensure good preview
  tempView.Layers[idx].PosX := 0;
  tempView.Layers[idx].PosY := 0;
  tempView.IO.Params.IEN_StoreBackground := False;
  tempView.IO.SaveToFileIEN( SelLayerFilename );
finally
  tempView.Free;
end;


Nigel
Xequte Software
www.imageen.com
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: