Jump to content

David Schwartz

Members
  • Content Count

    1189
  • Joined

  • Last visited

  • Days Won

    24

Everything posted by David Schwartz

  1. David Schwartz

    How to create a grid that looks like this

    I'm curious how to create a grid of colored blobs that look like this, rather than your usual array of squared-off cells. No gridlines, just colored blobs with some text in them. The fixed row and column are gray with text in them. I'm not even sure how this one was created, but was asked if it's possible for my Delphi app to make something like this.
  2. David Schwartz

    How to create a grid that looks like this

    I found a component janShape V.4 here: http://sodev.webzdarma.cz/show.php?page=Panel&la=&kateg=Forms It seems to be a newer version than jvShape that may be what's in the Jedi library. I got it to install in D10.4.2 with minimal effort, but I can't get either version to do very much. You can drop an instance of it on a form and it's a small square white box that resembles a TShape. I set the Caption and it shows up as very light-green against white bg and is very hard to see. Changing the Pen color does nothing. Changing the Brush color does nothing. Setting the Shape does nothing. Almost every property that's changed issues an Invalidate call, so it should update what's displayed. I do very little with the Canvas directly, so I'm not sure what I'm missing. Is anybody familiar with this or how to get it to actually show something useful? (Unfortunately, there's no sample included anywhere that I can find.)
  3. I've noticed that the Refactoring in 10.4.2 can't Rename variables that are defined inline, only those that are defined between the Procedure/Function line and the opening 'begin'. In fact, the more inline vars I use, the less often I see the ability to rename even things defined in the class declaration up in the Interface section. I haven't seen anything mentioned about this.
  4. Ahh, I didn't notice that. But ... I've seen stuff like that in newer code. Maybe it just never got refactored.
  5. What's the problem with just saying: Exit(False) instead of using a goto to say: Result := False; Exit;
  6. Couldn't you derive a child class, redefine the properties to reflect those in the ancestor class, then add the necessary attributes to them?
  7. David Schwartz

    No StringHelper for saving to file?

    Well, there are a few ways to do that, and all just take a few lines of code.
  8. David Schwartz

    How to create a grid that looks like this

    I'm not buying an entire huge library for one simple UI feature. The TjanRoundedButton solves the problem from a visual standpoint, although it's not as easy to work with as I'd like. (My Delphi license is up for renewal as well, and it ain't cheap either. That library is 2/3 the cost of my Delphi renewal. I only wish I could force everybody to give ME a mandatory 4% raise every year the way EMBT does with their maintenance deals.)
  9. David Schwartz

    upcoming language enhancements?

    The last couple of times I tried to get a beta, the code was released before the beta team responded to my request. So I don't bother asking now.
  10. Many years ago I found some Delphi code in units I was working with that looked odd. I stared at it for quite a while and finally realized the problem. It was written by a guy who had been working in MUMPS for a long time and Delphi was relatively new to him. In MUMPS everything is an array, except a string is a string, whereas in Delphi a string is an array of characters. In MUMPS, a "string" variable is more like a TStringlist in Delphi. In Delphi, the first character of a "string" returned by MUMPS would be accessed in MUMPS like this: firstChar := Copy( aStrList[0], 1, 1 ); There's a function in MUMPS called 'piece' that's equivalent to Delphi's Copy function, and it's used everywhere, often nested 2 or 3 levels deep in the same line of code just to extract a character or substring from something. In this case, a call being made to a service returned something that was put into a (Delphi) string. The code referred to theReturnValue[1] which is perfectly valid in Delphi, only it refers to the first character of the string. In MUMPS it's analogous to a TStringlist and refers to the first string [aka, piece(theReturnValue,1)] that was returned. Sometimes it would be empty (ie., '') and would throw an exception. Unfortunately, because of the way exceptions were handled, all we got was a notification that something somewhere tried to read memory at location 0. Another problem in this same code was like this: aReturnValue := theCallStatus; -- both of which were integers. But then it did this: if aReturnValue <> '0' then ... Several of these calls returned a value of zero (0) on success, and several returned a value of one (1) on success and zero on failure. SIDE NOTE: the devs here paid no attention to Hints and Warnings from the compiler, so there were literally hundreds when we did a build. I'm sure there were some that related to these code constructs, but they were all ignored. In this case, the code was checking for a failure, and was equivalent to: if aReturnValue <> $60 then ... The return on success was one (1) so most of the time the logic worked and was consistent with what you'd think by reading the code -- it wasn't $60 either. But sometimes it would return a zero and the test failed to notice that the call itself failed. The purpose of the test was to determine if the returned data was valid or not, and the test failed to recognize that the call failed, and it was processed normally, ultimately returning a success code to the caller in virtually every case, even when there were errors. The first thing it did in many cases was try to access something from an empty TStringlist, which threw a List Index Out Of Bounds error. Again, because of the way exceptions were being handled, all we knew was something somewhere threw an LIOOB error, but not where. (Besides, it was a long ways from where the TStringlist was created.) Since the code returned a success flag (because the failure wasn't detected), something way downstream would eventually throw another exception, usually when it tried to use some random data it thought was valid, as an index into a database, which threw a database exception that was impossible to trace back to the code shown above. This resulted in a steady stream of intermittent errors that could never be reproduced or diagnosed. The QA Dept concluded they were just spurious user errors on the part of the customer. I don't know what these kinds of mental translation errors are called, but in normal human parlance they'd probably be called a faux paus. I found a total of 7 distinct forms of these all used in conjunction with the same basic interface call. The programmer used a "copy-and-paste" style of programming, so he'd copy 20-30 lines of code from one place and paste it into the code where he needed it, faux paus and all. I found over 100 places where he pasted this code, and there was an average of 4 of these faux paus errors in each one. I fixed about 20 of them in the most used parts of the code, and the performance of the entire system improved enough that several people noticed it. Also, the spurious errors disappeared. (I was actually told to revert the changes because at this place, Development was not allowed to submit bug tickets. Only QA and the customer could do that. The errors from these bugs were data-dependent and impossible to reproduce, so they were never documented properly enough to warrant being fixed.)
  11. David Schwartz

    upcoming language enhancements?

    Anything along that line would be fine by me. The IfThen methods don't work in all cases and there's no alternative.
  12. David Schwartz

    How to create a grid that looks like this

    Well, I can get that, but it's the only thing I found that does what I'm looking for. And it was written for D3, D4, D5. It comes with source and isn't very complicated. And it compiled and ran with no issues. I'd have thought that somewhere in their vast array of stuff, TMS might have something, but I asked and Bruno said they don't. Raize has something that works under FMX, but this is a VCL app at the moment, and I'll be moving it to use TMS FNC components so I can webify it, so I may have to adapt it anyway. But for now it lets me keep moving forward.
  13. David Schwartz

    upcoming language enhancements?

    Yeah, all it says is, "Add Delphi language extensions for increasingly powerful coding" That's more than was said about ALL language extensions added in the past few releases. Given that it's singled-out in this release -- at the very top of the list, no less -- suggests maybe more is planned than one might expect. I'm also hoping they'll provide a way to generate code for smaller ARM platforms like Raspberry Pi devices and a wider array of Linux environments. 15 years ago, a PC with the power that a RPi 4 with a 1.2GHz CPU and 4GB of SD storage has on it was pretty damned expensive, and we used D4-D7 to write code for smaller environments. Given that a lot of that stuff is programmed using interpretive languages like Python, maybe Delphi could emit javascript/ASM (whatever it's called) that's easier to host on smaller platforms like this.
  14. David Schwartz

    upcoming language enhancements?

    Well, the roadmap lists "Language enhancements" as the first thing in the list for this upcoming release, but I've not seen anything specific. They often start discussing more details as the public beta gets rolling. A lot of stuff they list has resulted in some discussions with details being released. The language enhancements are almost always a surprise. But for them to actually mention it suggests they've got something more significant planned. <RANT> Delphi seems so far behind the curve when it comes to newer language features found in most contemporary languages that it has become silly. I'm tired of people who fancy themselves as highly muscular defending the lack of a jack for this type of car because it just wouldn't be the same if you didn't have to lift the car yourself to change a tire. Those "other cars" need a jack, but people who use "this car" ... BAH! We don't need no stink'n jacks! Just work out more and bulk-up those muscles! Ya, ya, ya ... and people wonder why the use of THIS type of vehicle keeps going down year after year. The vendor should put an effing jack in the trunk and anybody who doesn't want to use it can just forget it exists. Makes you wonder about all of the macho-men who objected to the use of replacing cranks on cars to get the motor running with electric starters. Delphi would be the last auto maker left without electric starters, because it would be seen as "too much like a Ford" or some other vehicle! There are around a dozen things that are found in most contemporary languages today that are missing from Delphi, and the only justification I'm aware of is because a lot of Dephi people like to scream, "we don't need no stink'n xyz or it would be too much like some other language!" Well, ya know what? All of those OTHER languages have GROWING USER BASES! Delpih keeps shrinking. Maybe saving time by having common-sense syntactic stuff found in most languages today is more important than some people think. Programmers DO LIKE TIME-SAVING FEATURES, ya know? For example, I tried using IfThen in a few places this past week and it got me into trouble ... when are we going to get a trinary operator to avoid having both options evaluated? If you think it's too much like something in some other language, just don't use it. You're free to use as many lines of code to replace a simple expression as you like. Nobody is gonna stop you! If that's not enough, switch to assembly language. (Remember, high-level languages evolved to SIMPLIFY programming vs. what assembler requires!) You can short-circuit multiple expression evaluations using logical operators (AND, OR) but that doesn't work for unassigned objects and in method calls that have side-effects, among others. Many OOP languages are now allowing a '?' to be put after assignment statements on references to objects that may be null to allow them to only work if the references are non-NULL. These are very common use cases that have evolved simple syntactic solutions in other languages to avoid multiple lines of code to address them otherwise. They're only cryptic to read if you never write code that uses them. (I rarely use things from the heap that require the ^ operator, so that stuff looks cryptic to me. But I'd never advocate that it be removed from the language for that reason!) I'm just hopeful we might be seeing some of this stuff finally showing up in Delphi (10-20 years later than other languages). I was looking at some of the code I've written in the past few days, and a lot of it is so highly idiomatic in given contexts that you'd think there would be a way of condensing it into simpler expressions without having to resort to stuffing it into subroutines or adding it to helper classes. That would only hide it away rather than simplify how it's expressed anyway. I have a feeling I'll be long gone before programming languages begin to incorporate features that let you reduce common idiomatic expressions into new syntactic structures other than subroutines. (Generics barely scratch the surface, and have a ton of limitations.) A lot of times we can't even use subroutines to simplify things in Delphi because you cannot use property names in var and out parameters on method calls, so you can't create a generic routine to pass back values to properties. You have to write a routine that's tightly-coupled to the class so it can set the properties internally, making what it's doing far more opaque than is needed. Or you just need a separate assignment statement explicitly setting property values one by one I was looking at some C++ recently ... I don't recognize any of the crap that I guess is now needed to get it to do what you need. it looks nothing like it did 20 years ago. I guess they call that "progress". </RANT>
  15. David Schwartz

    How to create a grid that looks like this

    That's not "one more dependency" to me, it's "hundreds of lines of code I don't need to (re)write and maintain". It's kinda like a homebuilder "buying lumber from a supplier [a dependency]" vs. "cutting down your own trees and making your own lumber". The FlowPanel and GridPanel don't work very well, so I manually placed them on a regular panel. It gets me the visual layout that's needed.
  16. David Schwartz

    How to create a grid that looks like this

    I found an old component TjanRoundedButton on Torry's that I can put on a FlowPanel that gets me what I need.
  17. David Schwartz

    Google GMB via Delphi?

    Has anybody used Delphi to connect to Google's GMB API? https://developers.google.com/my-business/preview/reference/businessinformation/rest They seem to have several different options, and it looks like they'll be migrating to a whole new API shortly. I've worked with different APIs, but nothing from Google yet. Curious if there's anything Delphi requires that's notable? I notice that most vendors don't have a Delphi sample, although sometimes I've seen that people have contributed one. Is there a repo anywhere that's used to post examples like this?
  18. David Schwartz

    Google GMB via Delphi?

    They're not all created equal... I had to hire someone to do it for an Amazon API and it took him way longer than he thought it would. So I thought I'd ask first this time.
  19. If I'm at the end of a method that I got into using F7 (step into method) and I hit F7, it goes into RTL code that manages the stack and other stuff in the RTL. I just want to return to the calling method. There's a setting somewhere to disable this, but I cannot seem to find it anywhere. Where did it get moved to?
  20. David Schwartz

    D10.4.2 where's setting to not debug into RTL ?

    That's what I was looking for. I forgot what it was. My memory is slowly losing bits... Thanks!
  21. I've got a bunch of things (n=4 .. 40 or so) I want to execute in parallel because each one takes a varying amount of time (eg., 5 to 20 seconds). All are calls to the same synchronous function with different parameters. I don't know if I need a task pool or not, because they're not doing anything while waiting to complete. Upon completion they'll receive a 10k-50k packet of response data. They all have unique names, and I'd like to put them into something like a TListView to provide visual feedback to the user about their current state, eg., pending, started, and finished + a status code. I want to update a line in the TListView corresponding to each task when it changes state. And when they're ALL completed, enable a "Continue" button that can then be clicked. Looking at the parallel tasking documentation, it seems I can wait for ANY ONE of them to finish, or for ALL of them to finish. The examples I've found simply mirror this model. I want to wait for EACH ONE to finish and do something slightly different (update a different line item in a VCL control) upon their termination, then do something else (enable a button) when they've ALL finished. I'd like to find an example of this approach to study.
  22. David Schwartz

    A screen mirroring utility

    mirroring 360
  23. David Schwartz

    gridlines in listboxes

    It seems like the only list-type control that gives you the option of showing lines is TListView. Is there a simple way of adding grid lines to other common list controls, like TListBox? (I don't do much with custom drawing stuff.)
  24. David Schwartz

    gridlines in listboxes

    I'm asking about how to add lines to list-like controls. TListView has a checkbox. TListBox has nothing. A lot of other libraries have simlar types of list controls and none of them offer lines either. I'm just curious how one would go about doing that. Saying "use something else" isn't addressing the question, but it may be an option in some circumstances.
  25. I have a situation where I've got a list of names and a list of places. I want to create a grid that displays a color in each cell that represents some data, sort of like a heat map. Think something like "how many people named Hans visited this place in Seattle during this date range?" So the gist of it is that you go through each combination of x (eg, name) and y (eg, place) then set the color of the corresponding cell to some normalized value. (this is not about the colors or even what's in the cells) There's a first pass goes through each (x,y) pair and does some queries to collect data, then saves it. In my mind, this is kind of like a stringlist with name=value pairs, where each 'name' is an (x,y) pair and the 'value' is an object (eg., another stringlist) that conains relevant data found for that specific pair. The next pass processes the data and extracts relevant numbers, then assigns something like a color value (in this case). There will be ways of filtering the data to offer different possible viewing models, which is why I read all the data first, then process it separately. (eliminates the need to re-issue the same queries over and over.) Each time the filter is changed, the data is re-analyzed and the results displayed. Possible ways I see of organizing this data include: (1) array of array (2) list of lists (3) a dictionary that uses each (x,y) pair as the key and saves the data as the value. Then it would cycle over them and split the pair to get the (col,row) for accessing a grid cell. (4) something else (?) I'd rather not have to do everything with a nested loop, and there's not much to do once the color has been determined other than use it to set the color of a corresponding grid cell. It's just a heat map that you look at. The user is MAINLY interested with what's in the SERIES of heat maps that are created over time so you can see how the data corresponding to the same (x,y) pairs changes over time. So what's of most interest is ... it's a stack (ie, LIST) of 2D heatmaps. Which I guess makes it a 3D data organization. What's the simplest way to organize and use the heat map data? (1), (2), or (3)? or maybe you have a (4) in mind?
×