filename truncation like in MC

English support forum

Moderators: Hacker, petermad, Stefan2, white

User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

E.g. I have file This is a very-very-very long file name and this is a very-very-very long file name and this is a very-very-very long file name and this is a very-very-very long file name and this is a very-very-very long file name.txt but in panel I see only This is a very-very-very long file name and this is a very-very-very long file name and this is a very-very-.. txt (when I hovew file by mouse I can see full name in tooltip).

Also TC have INI parameter BriefViewWidthLimit that allows to limit column width. If I set limit to e.g. 300 I see only This is a very-very-very long file name and th.. txt.

So TC truncates filename if it doesn't fit the panel width and shows ".." at the end of name. Tooltip may be used to see full name, and a hotkey may be sssigned for displaying such tooltip. Why it doesn't satisfy you?

PS. I don't think that truncating middle part of name is always better than truncating last part of name. And, as people said, in case of variable width font it may be hard to cut middle part.
mrbeeye
Junior Member
Junior Member
Posts: 85
Joined: 2004-05-03, 02:56 UTC

Post by *mrbeeye »

MVV wrote:And, as people said, in case of variable width font it may be hard to cut middle part.
Well, I've managed it. Here's my code (not perfect just enough to be proof of concept):

Code: Select all

procedure TfrmMain.Truncate;
var
   TextWidth, AreaWidth, half: Integer;
   S1, S2: string;
begin
     TextWidth := TruncatedFilename.Canvas.TextWidth(TruncatedFilename.Caption);
     AreaWidth := TruncatedFilename.Width;

     while (TextWidth > AreaWidth) do
        begin
         half := Length(TruncatedFilename.Caption) div 2;
         S1 := Copy(TruncatedFilename.Caption, 1, (half - 1));
         S2 := Copy(TruncatedFilename.Caption, (half + 2), (Length(TruncatedFilename.Caption) - half - 1));

         TruncatedFilename.Caption := S1 + '~' + S2;
         TextWidth := TruncatedFilename.Canvas.TextWidth(TruncatedFilename.Caption);
        end;
end;

TruncatedFilename is TPanel.
I can post a link to demo application so everyone can test it. I've tested it with fonts like Arial, Courier New, MS Sans Serif and Verdana.
User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

In case of fixed width fonts task is quite quick and easy and doesn't require any loops. But lets count processor ticks required for suggested example function...

E.g. filename length is 500 characters and column width is 50 characters, and your algo (if I understood it correctly) cuts 1 character per loop (plus previous '~' char). So you need to call Copy function ~800 times and then call Concat function ~400 times and then call TextWidth method ~400 times... And all theese functions have linear complexity.

And all this just for truncating middle part of filename... If we have just one file in panel its OK but if we have thousands of files...

BTW its much faster to use Delete function call and assign one character to '~' char instead of two Copy function calls and one Concat function call. So you need just to delete middle character and then assign new middle character to '~':

Code: Select all

procedure TfrmMain.Truncate;
var
   AreaWidth, half: Integer;
   S: string;
begin
     AreaWidth := TruncatedFilename.Width;
     if (TruncatedFilename.Canvas.TextWidth(TruncatedFilename.Caption) <= AreaWidth) exit;

     S := TruncatedFilename.Caption;
     repeat
         half := Length(TruncatedFilename.Caption) div 2;
         Delete(S, half, 1);
         S[half] := '~';
     until (TruncatedFilename.Canvas.TextWidth(S) <= AreaWidth);

     TruncatedFilename.Caption := S;
end;
Also for large filename lengths it is much faster to use binary algo that will try to cut N/2 characters, then N/4 or N/2+N/4 etc. So for 1000 characters it will require only 10 loop passes instead of up to 950 for linear algo.
Post Reply