Jump to content

David Schwartz

Members
  • Content Count

    613
  • Joined

  • Last visited

  • Days Won

    6

David Schwartz last won the day on April 13

David Schwartz had the most liked content!

Community Reputation

170 Excellent

Technical Information

  • Delphi-Version
    Delphi 10.4 Sydney

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. 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.
  2. David Schwartz

    A screen mirroring utility

    mirroring 360
  3. 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.
  4. 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?
  5. David Schwartz

    gridlines in listboxes

    A listbox is really easy to use. A stringgrid is not a simple replacement for a listbox.
  6. 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.)
  7. David Schwartz

    TJSONObject.Format bug

    Ok, I figured it out. Thanks!
  8. David Schwartz

    TJSONObject.Format bug

    EDIT: Actually, it's implemented in DW.REST.Json.Helpers. I cannot find any other reference to Tidy in the code base that I just pulled down from github. TJsonHelper = class helper for TJson public class function FileToObject<T: class, constructor>(out AObject: T; const AFileName: string; AOptions: TJsonOptions = [joDateIsUTC, joDateFormatISO8601]): Boolean; static; class procedure SaveToFile(const AObject: TObject; const AFileName: string); static; /// <summary> /// Replacement functions for TJson.Format, which does not format correctly /// </summary> /// <remarks> /// Overload that takes a string parameter has been modified so that it should also work for /// JSON which is not generated by TJsonValue.ToString /// Please use this function with CAUTION!! It still may not cater for all situations, and is still not perfect /// </remarks> class function Tidy(const AJsonValue: TJsonValue; const AIndentSize: Integer = 2): string; overload; static; class function Tidy(const AJson: string; const AIndentSize: Integer = 2): string; overload; static; end; . . . // Now based on: https://pastebin.com/Juks92Y2 (if the link still exists), by Lars Fosdal class function TJsonHelper.Tidy(const AJson: string; const AIndentSize: Integer = 2): string; const cEOL = #13#10; var LChar: Char; LIsInString: boolean; LIsEscape: boolean; LIsHandled: boolean; LIndent: Integer; begin Result := ''; LIndent := 0; LIsInString := False; LIsEscape := False; for LChar in AJson do begin if not LIsInString then begin LIsHandled := False; if (LChar = '{') or (LChar = '[') then begin Inc(LIndent); Result := Result + LChar + cEOL + StringOfChar(' ', LIndent * AIndentSize); LIsHandled := True; end else if LChar = ',' then begin Result := Result + LChar + cEOL + StringOfChar(' ', LIndent * AIndentSize); LIsHandled := True; end else if (LChar = '}') or (LChar = ']') then begin Dec(LIndent); Result := Result + cEOL + StringOfChar(' ', LIndent * AIndentSize) + LChar; LIsHandled := True; end; if not LIsHandled and not LChar.IsWhiteSpace then Result := Result + LChar; end else Result := Result + LChar; if not LIsEscape and (LChar = '"') then LIsInString := not LIsInString; LIsEscape := (LChar = '\') and not LIsEscape; end; end; end.
  9. David Schwartz

    TJSONObject.Format bug

    Yes, I know that. Here's the problem: implementation {$R *.dfm} uses StrUtils, Math, ShellApi, DW.REST.Json.Helpers; The file is in the same folder as the other project files. I even included the unit in the project. So there's no reason the compiler shouldn't be able to find this method. ------------------- JSON_mmo.Text := Tidy( google_srch.TheResponse ); [dcc32 Error] Main_form.pas(533): E2003 Undeclared identifier: 'Tidy' JSON_mmo.Text := TJSON.Tidy( google_srch.TheResponse ); [dcc32 Error] Main_form.pas(533): E2003 Undeclared identifier: 'TJSON' JSON_mmo.Text := JO.Tidy( google_srch.TheResponse ); [dcc32 Error] Main_form.pas(533): E2003 Undeclared identifier: 'Tidy' -------------------- FWIW, I get red squigglies on a numerous classes and methods that the compiler things are not defined, but it compiles just fine and runs. (This is D10.4.2.)
  10. David Schwartz

    TJSONObject.Format bug

    This looks great, except I can't get the compiler to find the Tidy method: var JO := TJSONObject.ParseJSONValue(google_srch.TheResponse) as TJSONObject; JSON_mmo.Text := JO.Tidy( google_srch.TheResponse ); [dcc32 Error] Main_form.pas(533): E2003 Undeclared identifier: 'Tidy' I have the unit in the Uses clause and even included it in the project.
  11. David Schwartz

    TJSONObject.Format bug

    I dunno why it would barf either, except when I went through the raw response text with an editor and replaced all '%' characters with ' pct' the problem disappeared. Maybe it's actually using the normal Format method there? (I have not dug into it.)
  12. David Schwartz

    TJSONObject.Format bug

    It seems if you have quoted strings that contain things like "... 100% satisfaction ..." or "... a 10% discount..." in an input string, the call to doc.Format here: doc := TJSONObject.ParseJSONValue(the_resp) as TJSONObject; JSON_mmo.Text := doc.Format(DEF_INDENT); // <----- chokes on the "% <space> <next char>" sequence saying it's not a valid format. Is there a way to escape these % chars or do something that doesn't require deleting them?
  13. I've recently encountered some web apps that use "bubbles" (rectangles, circles, etc.) that you drop onto a canvas that are associated with some specific logic. You can "zoom-in" and perform more detailed design of those things that goes far beyond just editing values in an Object Inspector. (eg., a whole web page editor with access to templates, libraries of various media, etc., for creating the landing page.) Then you can connect them to one or more other bubbles to represent a flow. It's roughtly similar to how the LiveBindings Designer works, only these are much higher-level operations with access to a larger variety of object editors. The few I've seen all seem to be using a very similar (if not the same) UI framework. The approach they're taking represents a rather high-level of graphical programming. They're all very application-specific, but allow non-technical users to build fairly complex apps that don't require a single line of programming. They're used to design apps that implement logic supported on a given SaaS site. For example, one lets you create a web landing page with several fields on it. If one of them is a phone#, then when the user clicks the Submit button, you go to a bubble that says, "If there's a phone# given, then send it to this email or message#". It also logs the submission, adds the data to a mailing list, and does some other stuff. This logic is all built-in, although it works with Zapier to let you add logic to unrelated stuff if you want. We still don't have a view of our apps from inside the IDE that shows the forms and flow between them on a big canvas in the same way that DB designers have had for DB layouts for at least 15 years now, let alone some way to build a UI like this within Delphi. TMS has their Diagram Studio, although it's rather limited. There's also Mitov's OpenWire framework. I don't know what these web-based frameworks are, but they seem to be gaining in popularity. Is anybody doing this with Delphi (or even C#)? Or are we going to have to abandon this ship to get access to UI/UX trends that web devs seem to be leap-frogging over us and providing to customers?
  14. David Schwartz

    JSON parsing question

    I'm dealing with an API that returns its data in a big JSON object that can vary from one request to another because the data being returned is somewhat dynamic. (Some is always there, and some is not.) It's structured generally like this: { section1: {...}, section2: {...}, section4: {...}, section7: {...}, . . . } Some sections consist of sub-objects (ie, {name : {...}} things) and some consist of array of JSON objects (ie, { name : [ ... ] } things) where the members are also JSON objects. Most examples I've seen approach this from the perspective that you know exactly what all of the 'name' values are for each object. In this case, I know there are a bunch of sections and sub-sections, but I don't necessarily know what all of the 'name' parts are. Also, you can infer from the above that there are sections 3, 5, and 6 that are not present in the results of this particular request. A section might not be there until you see it show up sometime; then it's like, "Oh, look at that ... something I haven't see before!" That is, it's not like the server in this case always returns, say, 15 sections, whether some are empty or not. Also, the sections may not always show up in the same order. What's the best way to parse this sort of thing? Part of what I'm not clear about is that I can ask for a Count on the number of things in an Array then iterate over the array, but what about the parts of a list -- like the sections named above? In my mind, I'd approach it using a Case statement, where I'd iterate through the list and drop each section name into the Case. If there's a match, then it would processed. An Else clause would handle any that aren't known yet, mostly for documentation purposes. (I'm ignoring the fact that Pascal's Case statements are still stuck in the 1970's and don't accept strings like most other contemporary languages today...) I'm working with Delphi's built-in JSON Objects Framework, although I could be persuated to use something else if it's noticeably simpler. None of the examples in the docwiki make much sense because they assume you already know the structure and names of everything being sent, as well as the order in some cases. What I *DO* know is the section names of particular interest, and within those sections there are specific elements I know by name that I want to extract the values from. Some of them are in secton sub-objects and some are in arrays of objects in a section. I also know which of these sections contain an array of objects and which are just sub-objects. Or said another way, I know that section values either look like a record or class (as opposed to a single-element array), or they're an array of records or classes.
  15. David Schwartz

    Out parameter is read before set

    Yes, exactly! Most of these I was able to solve, although some took quite a lot of head scratching.
×