-
Content Count
2312 -
Joined
-
Last visited
-
Days Won
119
Posts posted by Anders Melander
-
-
12 hours ago, Angus Robertson said:The latest ICS v9 release has packages for Delphi 12, but did not need any changes for D12 other than VER360.
Please stop using VERxxx. It's been possible to do {$if CompilerVersion >= XX} since Delphi 6 or 7.
It's so annoying having to edit the .inc files of various 3rd party libraries with each new version of Delphi because they're designed as if the latest version = the last version.
10 hours ago, Stefan Glienke said:As one of the few lib devs that actually test their code on all supported Delphi versions I object - dproj files so often have incompatibilities in them.
Yes, it is possible to have only multiple dproj files but only one dpk they refer to and put the libsuffix stuff into an inc file referencing that one on the dpr (have done that, works fine) but it is tedious.
I rather copy the latest version when a new one comes out/is in beta.
Graphics.32 uses {$LIBSUFFIX AUTO} for the D11+ packages. The earlier packages are manually maintained by using a diff tool to keep them synchronized with a master. The master usually comes from the latest supported Delphi version.
There's no way I'm wasting disk space on old versions of Delphi just to maintain the package files. I have the latest version, and the few versions required by my job, and that's it.
- 4
-
Strange... It's like there's an echo in here.
-
14 minutes ago, Michael Taylor said:I wanted to call my constructor "From" instead of "Create" to signify that no memory allocation takes place, and Free won't be necessary.
Naming the constructor "Create" is just a convention. You can name it anything you like.
Thus naming the constructor "From" will not make a difference.
Here's your problem:
20 minutes ago, Michael Taylor said:constructor Span.From(item: ItemType, color: Color); begin Color := color; Item := item; end;
Pascal isn't case sensitive so that code does nothing. Prefix your parameter names with "A" (i.e. name them AItem and AColor in this case) to avoid problems like that.
FWIW, if you want to avoid memory allocation (i.e. allocate your object on the stack instead of the heap), make it a record instead.
- 1
-
On 7/27/2023 at 6:50 PM, Lars Fosdal said:the default 256 color Windows palette
There is no default 256 color palette. Old version of Windows "reserved" 16 fixed colors while new versions reserve 20 fixed colors.
https://en.wikipedia.org/wiki/List_of_software_palettes#Microsoft_Windows_default_20-color_palette
Changing the pixelformat to pf8bit forces the bitmap to use a color palette. I.e. instead of each pixel explicitly specifying the RGB color values, the pixels will contain an index into a palette of 256 colors.
The colors in a palette generated by Windows will partially depend on the system palette which again depends on the Windows theme.
https://learn.microsoft.com/en-us/windows/win32/gdi/system-palette-and-static-colors
https://learn.microsoft.com/en-us/windows/win32/gdi/default-palette
If you want a predictable result then you need to generate the palette using a predictable method: Either use a static palette or generate one using color quantization. There are methods in the GifImg unit for both solutions.
https://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.Imaging.GIFImg.ReduceColors
- 1
-
5 hours ago, TazKy said:A developer uses the best tools for any given situation.
Not necessarily.
An emphasis on a specific library is most likely caused by existing use and thus an investment in that library. Regardless of "bestness".
-
45 minutes ago, TazKy said:What is interesting is the strong emphasis on TMS.
Why is that interesting?
-
4 hours ago, eivindbakkestuen said:who knows where the next 20 will take us
Support for FireDAC, one could hope
-
-
1 minute ago, luebbe said:An exe produced by someone else with 10.4.2 is ???
"Irrelevant" is the word you're looking for 🙂
If it works for you with 11.x then there is no problem.
-
5 minutes ago, Stano said:Unfortunately, all the links to your page show me a blank "screen".
Then it's probably a problem with your browser. [Ctrl]+F5 to do a forced reload or use another browser.
-
2 hours ago, luebbe said:So it looks like a regression in 10.4 (or 10.3) to me.
You need to have someone compile and run your project with 10.4.2 in order to conclude that.
Right now you only know that your exe reproduces the problem and that an exe produced by one other person doesn't.
-
2 hours ago, Roger Cigol said:Without new members the forum has signed it's own death warrant (even if it is a slow death).
To be "Musked" I believe it's called
- 2
-
5 hours ago, Stano said:Strange. The URL seems correct so it's probably just a temporary hiccup with the redirection.
4 hours ago, Stano said:- 1 Translate the component itself and get this translation into the program translation
- 2 Always translate it in the program
- 3 Of course, I only want to translate it once
2: You translate the application using the component. If you use the component in multiple projects then you will have to do the translation for each project. That's unfortunately just the way Delphi localization is designed.
You can save the translations to the Translation Memory and share that between projects, but it's an almost completely manual process.
4 hours ago, Stano said:Translation into other languages. I'm starting from programs that contain language files.
Some user gets an English version of some file. He translates it into his language- 4 What do I send him and
- 5 how do I get it into the program
All the translations are contained in the translation project file (the xlat file).
A translator will need amTranslationManager.exe and the .xlat file. I would recommend that you also create a portable-mode configuration file so the translator doesn't need to install anything. I think the docs mention that.
Once you receive an updated xlat file from the translator you will have to merge that into your local xlat file using some sort of text merge tool. I suggest placing the file under version control and then use that to do the merge.
There is no functionality in BTM to merge two translation project files, although that would be a handy feature.
4 hours ago, Stano said:When you posted the first version, there was some description. The only thing I remember is that it automatically loads the language according to the OS. If no such language exists in the translation it will run the base language (source)
- 6 But users sometimes want to use a different language than they have the OS language
- 7 Is there such an option?
It's still there: https://bitbucket.org/anders_melander/better-translation-manager/src/master/#markdown-header-deploying-a-localized-application
The hello_world demo contains an example of how to allow the user to choose the language.
As far as I remember there are some other methods buried in the announcement thread:
4 hours ago, Stano said:I have created a component editor. It writes to *dfm.
- 8 Can *dfm be translated or do I have to, is it better to use another way?
If your text is written as a string (or stringlist) property, then it can be translated.
4 hours ago, Stano said:A) Some components have the same property. For example Caption.
- 9 Do I need to translate all the same occurrences? That's pretty much a no-brainer
- 10 Screw translating them and hard use resourcestring
Yes. Individual properties on individual components are individually translated.
BTM will help you with the translation of identical texts, but it will not do it automatically since that might not be what you want. Often context matters.
For example, if you translate "Cancel"->"Fortryd" then it will prompt you to translate all other occurrences of "Cancel" using the same translation. It will even offer to translate texts that "almost" match such as "cancel", "&Cancel", "Cancel!", etc.
4 hours ago, Stano said:Such a trivial question at first glance. But I have no experience with this:
- 11 How (methodology) and where is the best way to assign each resourcestring to each component?
- 12 Will this work in FormCreate?
Use resourcestrings just like you would use a string constant. The only thing to be aware of is that the resourcestring name needs to be unique within the unit.
Resourcestrings are a language feature and as such it is processed by the compiler and the linker (with help from the RTL at runtime). FormCreate is a run-time thing so that doesn't matter; Use them where ever you want.
Some prefer to keep all resourcestrings in a separate unit, some prefer to have them at the top of the unit and some to have them declared locally where they are used.
I usually declare them with the most restrictive scope I can get away with:
unit Foo; implementation procedure DoFoo; resourcestring sFooPublic = 'This is a public, global resourcestring'; // Usable by all that use unit Foo interface resourcestring sFooPrivate = 'This is a private, global resourcestring'; // Usable within unit Foo procedure DoFoo; resourcestring sFoo = 'This is a local resourcestring'; // Usable within DoFoo begin ShowMessage(sFoo); end; end.
Note though that FreePascal doesn't support local resourcestrings. In FPC they must be declared globally (i.e. outside the methods/functions).
-
2 hours ago, Cristian Peța said:Use DistanceFromPointToLine
One needs to take into account that we're not dealing with lines but line segments. Lines have infinite length, while line segments have finite length.
We don't want to detect a hit beyond the end of the line segment:
I think the following one does the trick. I use it in a bitmap editor for scanline conversion of lines (the above image was made with it).
(* Distance from point to line segment. Let A=(xa,ya), B=(xb,yb), X=(x,y) Now, the line between A and B is given parametrically by V(k) = (1-k)A + kB = A + k(B - A) and adding the constraint 0 <= k <= 1 makes V(k) the line segment from A to B. Now, the line through X perpendicular to V(k) intersects V(k) when k equals (B - A) . (X - A) k = ------------------- | B - A |^2 So if k <= 0, X is closest to A, if k >= 1, X is closest to B, and if 0 < k < kp, X is closest to V(k). *) function DistanceToLine(X,Y, XA,YA, XB,YB: integer; var RunLength: Single): Single; function VectorLength(X1,Y1, X2,Y2: Single): Single; inline; begin Result := Hypot(X1-X2, Y1-Y2); // = Sqrt(Sqr(X1-X2) + Sqr(Y1-Y2)) end; var k: Single; dx, dy: integer; begin dx := XB-XA; dy := YB-YA; if (dx <> 0) or (dy <> 0) then begin k := (dx*(X-XA) + dy*(Y-YA)) / (Sqr(dx)+Sqr(dy)); if (k <= 0) then // Point before or at start of line segment Result := VectorLength(XA,YA, X,Y) else if (k >= 1) then // Point after or at end of line segment Result := VectorLength(XB,YB, X,Y) else // Point within line segment Result := VectorLength(X,Y, XA+k*dx, YA+k*dy); // = VectorLength(X,Y, (1-kp)*XA+kp*XB, (1-kp)*YA+kp*YB); RunLength := k; end else // Degenerate line begin RunLength := 0; Result := VectorLength(XA,YA,X,Y); end; end;
The result is the distance, the RunLength parameter can be used to determine where the projection of the point onto the line lies: before, on, or after the line segment.
A small optimization can be done since we're doing hit-testing and don't really need the actual, precise distance value. The VectorLength function uses Hypot (i.e. Pythagoras) to calculate the distance. Hypot internally does a Sqrt, which is an expensive operation. The Sqrt can be eliminated so we return the squared distance instead and then we just need to compare that value against the squared hit limit instead. I.e. if your hit limit was 4 then compare the squared distance against 4*4 = 16 instead.
- 2
-
I have attached an extraction of the BTM documentation I have.
As I said it was written for use with a specific project (called FooBar in this version) and as such contains references to the setup of that project (folders, config files, etc.) and it assumed that the initial translation project file and update have already been done.The source document, as mentioned, comes from Confluence so the formatting of the exported document is a bit wacky, but I think it should be readable.
Using_Better_Translation_Manager_-_Anders.Melander_-_Confluence_(2023-08-16_22_10_10).html
-
2 hours ago, Stano said:The one I wrote about is clean.
I have no idea what you are referring to.
-
Just now, Stano said:Some instructions for use.
Ah, that... Um... Eh...
I don't really have anything besides what's on the Bitbucket page. Well, actually, now that I think of it I think I have something in a corporate Confluence page somewhere, but I will have to revise it for public consumption and it's probably targeted for use with a specific commercial project. I'll look into it later tonight.
-
2 minutes ago, Anders Melander said:I'll get that fixed.
Done. The new version is 2.0.8628.33873
-
1 hour ago, Stano said:Please and what about the help?
What help is that?
55 minutes ago, Stano said:Save.
Yes, I see it.
Apparently, the feature branch wasn't merged correctly. I'll get that fixed.
-
8 hours ago, Mike Warren said:Does anyone have an idea on how I can achieve this?
- Convert the bezier to a polyline with a fixed limited number of points (whatever drawing routine you end up using already does this internally, you just need a lot fewer points for hit testing than for drawing a smooth line).
- Iterate the segments of the polyline and find the minimum distance from your point to the segments.
Even with thousands of beziers, you should be able to do this in no time at all (I'm guessing low milliseconds).
-
Fixed. The purge was rejected unless the project contained obsolete items with translations.
Get the new release (2.0.8628.30767) here:
Changes since the last release (2.0.8370.39904):
- Fix for unable to purge project unless it contains Unused translations.
- #43: Specify external PE resource module stub via command line
- #41: DeepL Integration
- Added Save As... action. Previously the Save action always prompted for filename.
-
Reproduced. I'll investigate now.
-
29 minutes ago, Stano said:Thank you. They cannot be described as "Do not translate".
No, you're right; They cannot.
30 minutes ago, Stano said:Assuming this means that you cannot purge them, can you zip the translation project (just the xlat file) and post it as a DM to me.
-
That's "obsolete" items. Items that existed in a prior version of your application but which have been deleted since they were first imported. That usually happens when you delete components or units.
You can't really hide them (that's a missing feature) but you can delete them:
Or you can just mark them "Don't translate" and hide them that way.
The reason they aren't just deleted automatically is that their translations (if they have any) can be reused by other items. For example, if you rename a component, then the translation-to-component link is broken but by comparing the source texts, BTM can move the link to the new component so the translation isn't lost. The Recover action does this.
The translations of obsolete items are also still used as translation suggestions.
Call for Delphi 12 Support in OpenSource projects.
in Delphi Third-Party
Posted
Works for me: