קטגוריה: Lazarus

TAChart – חלק רביעי

בחלק הקודם התעסקתי רק על הפיכת הטבלה לדבר לפעולה התשרת את הוספת הערכים לעוגה. הגיע הזמן אבל ליצור עוגה, כי אם מקודם הייתי קצת רעב, תארו לכם מה קורה אחרי ארבעה ימים…

יצירת הגרף

את פעולת היצירה חילקתי לשני חלקים:

  1. אתחול המידע
  2. הזנת הנתונים לעוגה

TAGraph עובד עם "סדרות". הסדרות הללו הן למעשה סוגי הגרפים עבור TAGraph. אתם בטח מבינים כי מן הסתם, סדרה בשם TPieSeries מדברת על גרף מסוג Pie.
התחלתי קודם בחלק האתחול. היות והוא צריך לרוץ רק פעם אחת, אבל הכנסתי אותו למתודה משל עצמו וקראתי לה בשם initpie. יצרתי גם שדה בשם pie מסוג TPieSeries שהוא גלובלי במחלקה של החלון.

בראש ובראשונה אני רוצה לאתחל את pie, אח"כ לספק לו כותרת. במידה ואתם רוצים (אני לא אוהב את זה במיוחד), ניתן גם להגיד לו לפצל כל פלח בעוגה.
לאחר מכן, אני החלטתי לטפל קצת באיך המקרא יראה, כולל איזה טקסט יוצג שם (עבודה עם חוקי format string של פסקל). גם החלטתי כי הקבוצה שאליה הגרף שייך היא קבוצה מספר 0.

לאחר המקרא, החלטתי להתחיל לטפל באיך כל נתון יקבל ייחס. החלטתי לתת צבע צהוב בהיר לרקע התווית, ושהעט המציירת אותה תהיה ברוחב 2 פקסלים.
התווית עצמה תציג גם את השם וגם את הערך של כל איבר בגרף.

לאחר מכן, החלתי לטפל קצת במקרא של Chart עצמו. והוספתי קבוצה מספר 0, בשם Pie. לאחר מכן, הוספתי את הסדרה שיצרתי:

procedure TForm1.initpie;
begin
  Chart.ClearSeries;
  pie          := TPieSeries.Create(Chart1);
  pie.Title    := 'Pie Chart';
  pie.Exploded := False;
  with pie.Legend do
   begin
     Multiplicity := lmPoint;
     Format       := '%2:s (%1:.2f%%)';
     GroupIndex   := 0;
   end;

  with Pie.Marks do
   begin
     LabelBrush.Color  := $80FFFF;
     LinkPen.Width     := 2;
     Style             := smsLabelPercent;
     OverlapPolicy     := opHideNeighbour;
     Visible           := true;
   end;

  with Chart.Legend do
   begin
     GroupTitles.Clear;
     GroupTitles.Add('Pie');
     Chart.AddSeries(pie);
   end;
end;

חשוב לזכור כי את כל הדברים האלו ניתן גם לבצע בצורה גרפית לחלוטין, אבל רציתי קצת להראות איך הקוד נראה, במידה ואנחנו בוחרים לעשות את זה בקוד.
היות ואנחנו יוצרים את pie, צריך גם לשחרר אותה. אז הלכתי לאירוע של החלון הנקרא OnDestroy והוספתי שם את הקוד הבא:

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Assigned(pie) then
    FreeAndNil(pie);
end;

וכך אני מונע דליפת זיכרון בקוד שלי, בעת סגירת החלון.

השלב הבא שלי, היה בעצם לספק את הנתונים עבור הגרף. וברגע שאני מסיים לספק אותם, הם מוצגים על המסך.
לשם כך הלכתי לאירוע של btnApply והוספתי שם את הקוד הבא:

procedure TForm1.btnApplyClick(Sender: TObject);
var i    : integer;
    acol : TColor;
begin
  if not Assigned(pie) then initpie; // first time applying ... it can have memory leak if we apply it every time
  pie.Clear;
  for i := 1 to sgGraphDetails.RowCount -1 do
   begin
     with sgGraphDetails do
      begin
        if Cells[2, i] = '' then continue; // empty content
        acol := clTAColor; // set color automatic
        if Cells[3, i] <> '' then // unless we choose one ...
          acol := StringToColor(Cells[3, i]);

        // Add the values
        pie.Add(StrToFloat(Cells[2, i]), Cells[1, i], acol);
      end;
   end;
end;

ועכשיו אנחנו גם מציגים את העוגה. הבעיה היא שאני עדיין לא יכול לאכול אותה, כי היא נמצאת רק בחלון 😦
הבטן מציקה לי מאוד, ואני חייב כבר לאכול את העוגה.

אז הגיע הזמן לייצא את התוצר החוצה.
למרות שיש הרבה מאוד סוגי תמונות אליהם ניתן לייצא, החלטתי לתמוך בהדגמה שלי רק ב6 סוגים נפוצים:

  1. Windows Bitmap (bmp)‎
  2. Jpeg (jpg)‎
  3. Portable Network Graphics (png)‎
  4. Portable Map Graphics (ppm)‎
  5. X Pixmap (xpm)‎
  6. SVG

לשם כך הגדרתי קצת את הפילטר של SaveDialog. אתן לכם לשחק איתו קצת, היות והוא מאוד פשוט להגדרה בצורה גרפית.
הקוד שכתבתי, עובד לפי הסדר שרשמתי כאן ובנוי לפיו.

למעט SVG, לייצא לפורמט מפת סיביות כלשהי, זה יחסית מאוד פשוט. הקוד האמיתי הוא עבור ה SVG.

procedure TForm1.btnExportClick(Sender: TObject);
var fs : TFileStream;
    id : IChartDrawer;
begin
  if not SaveDialog.Execute then exit;

  case SaveDialog.FilterIndex of // lets see what type of image they want
    1 : Chart.SaveToBitmapFile(SaveDialog.FileName);                          // bitmap
    2 : Chart.SaveToFile(TJPEGImage, SaveDialog.FileName);                    // JPeg
    3 : Chart.SaveToFile(TPortableNetworkGraphic, SaveDialog.FileName);       // PNG - our default
    4 : Chart.SaveToFile(TPortableAnyMapGraphic, SaveDialog.FileName);        // PPM
    5 : Chart.SaveToFile(TPixmap, SaveDialog.FileName);                       // XPM
    6 : begin                                                                   // SVG
          fs := TFileStream.Create(SaveDialog.FileName, fmCreate);
          try
            id                       := TSVGDrawer.Create(fs,true);
            id.DoChartColorToFPColor := @ChartColorSysToFPColor;
            Chart.Draw(id, Rect(0,0, Chart.Width, Chart.Height));
          finally
            fs.Free;
          end;
        end;
  end;
end;

החלטתי להשתמש בסטטיסטיקה של w3school על דפדפנים, והשתמשתי בנתונים שלהם לחודש אוגוסט 2012.
זהו, עכשיו אפשר לקחת את התוצר ולאכול. בתאבון 🙂
tachart browser statistics

את קוד המקור, ניתן להורד מgithub.

TAChart – חלק שלישי

בחלק הקודם, יצרתי את הסביבה הגרפית ליצירת הגרף, בחלק הזה אתמקד בכל מה שקשור להכנה ליצירת הגרף עצמו, ובחלק הבא (שהוא האחרון), אתמקד בגרף עצמו וביצוא שלו לתמונה.

כתיבת קוד

החלטתי קודם להתעסק קצת ב"קוסמטיקה" שהיא קצת חשובה. הקוסמטיקה היא הוספה והסרה של שורות, וכן התגובתיות של הרכיבים. אבל הם חשובים מאוד כי רק באמצעותם ניתן בעצם ליצר את הגרף עצמו, וכן לאפשר או לא לאפשר פעולות למשתמש.

הלכתי קודם לכפתור הנקרא btnAddItem , לחצתי עליו פעמים, והוא פתח בעורך הטקסט מתודת Callback בשם btnAddItemClick. ניתן לראות אותה גם בObject Inspector במידה ונלך לטאב הנקרא Events. זהו אירוע ברירת המחדל של כפתור, ולכן הוא זה שבעצם הוגדר.

הקוד עבור הcallback מאוד פשוט. אנחנו הולכים להוסיף לו 2 שורות. הראשונה אומרת להוסיף עוד שורה, השניה הולכת לשים מספור מתאים לתא, ובכך נקבל מספורים כדוגמת "1, 2, 3" וכו' … פר שורה:

procedure TForm1.btnAddItemClick(Sender: TObject);
begin
  sgGraphDetails.RowCount := sgGraphDetails.RowCount + 1;
  sgGraphDetails.Cells[0,sgGraphDetails.RowCount -1] := IntToStr(sgGraphDetails.RowCount -1);
end;

השלב הבא יהיה להסיר שורה על ידי הוספת Callback עבור btnRemoveLastItem:

procedure TForm1.btnRemoveLastItemClick(Sender: TObject);
begin
  if sgGraphDetails.RowCount > 1 then
    sgGraphDetails.RowCount := sgGraphDetails.RowCount - 1;
end;

אנחנו גם בודקים, אם אנחנו לא חורגים מהגבולות שלנו, כאשר כאן מדובר בשאלה האם יש לנו יותר משורה בודדה, ורק אם כן, נבטל שורה אחת.

עכשיו נלך לעשות "טריק" פשוט. הפעלת וביטול פעולות של מחיקה ורינדור. אם אין מידע, או שורות, אני לא רוצה לעשות סתם פעולות, אשר לפחות ברינדור, הן לוקחות כוח מיחשוב שיכול להיות גדול, ובהסרת שורות, במידה ואין אפשרות, סתם תהיה "פרצה הקוראת לגנב".
לשם כך, הלכתי לטאב הEvents בחרתי ברכיב של sgGraphDetails, ובאירוע OnColRowDeleted. לחצתי עליו פעמיים, וכתבתי את הקוד הבא:

procedure TForm1.sgGraphDetailsColRowDeleted(Sender: TObject; IsColumn: Boolean;
  sIndex, tIndex: Integer);
begin
  btnRemoveLastItem.Enabled := sgGraphDetails.RowCount > 1;
  btnApply.Enabled          := sgGraphDetails.RowCount > 1;
end;

אני מבצע בדיקה לוגית (במקום שאלת if), האם יש יותר משורה אחת בודדה, ואם כן, רק אז לאפשר את הכפתורים.
אבל זה לא מספיק ! הרי מה קורה כאשר אני מוסיף שורה ?
אז חזרתי לטאב הEvents של sgGraphDetails, ובאירוע OnColRowInserted בחרתי מהרשימה את sgGraphDetailsColRowDeleted, ולמעשה יש לי שני Callbacks אשר מצביעים על אותו הקוד, רק מתרחשים בזמנים שונים.

השלב הבא הוא לחשוב מה קורה כאשר אנחנו בעצם רק יוצרים את החלון. הרי הכפתורים בברירת המחדל מאופשרים, אבל לא באמת ניתן למחוק או לרנדר משהו.
אז הלכתי לאירוע של הטופס עצמו, ויצרתי את הקוד הבא, ועל הדרך גם הוספתי עוד כותרת אחת רק בקוד:

procedure TForm1.FormCreate(Sender: TObject);
begin
  sgGraphDetails.Cells[0,0] := '#';
  btnRemoveLastItem.Enabled := sgGraphDetails.RowCount > 1;
  btnApply.Enabled          := sgGraphDetails.RowCount > 1;
end;

עד כאן הקוד מאוד פשוט נכון ?
זוכרים שזרקתי על החלון, רכיב דיאלוג של צבעים ?
הגיע הזמן להשתמש בו, ולקשר אותו בעצם לטבלה ששמתי.
אז הלכתי לאירוע של OnButtonClick ברכיב sgGraphDetails ולחצתי עליו פעמיים.
שם בעצם אני בודק קודם כל מה העמודה שלחצו בה, ורק אם זו העמודה הנכונה, אני מציג את הדיאלוג.
לאחר הצגת הדיאלוג, במידה והמשתמש מאפשר לי (כלומר לא לחץ על cancel), אני מוסיף את הצבע הנבחר.
התאוריה נחמדה, והיא נראת ככה בצורה מעשית:

procedure TForm1.sgGraphDetailsButtonClick(Sender: TObject; aCol, aRow: Integer);
begin
  if (aRow >= 1) and (aCol = 3) then
    begin
      if ColorDialog.Execute then
        begin
          sgGraphDetails.Cells[aCol, aRow] := ColorToString(ColorDialog.Color);
        end;
    end;
end;

אם חושבים על זה לעומק, הבעיה החמורה ביותר שיש היא האפשרות שהאחוזים לא יהיו מספר עשרוני.
אש צריך להגיד בקוד שבמידה ומזינים ערך לא חוקי, פשוט לא לקבל את זה בעת ההזנה (ולא אחרי).
לשם כך החלטתי לממש את זה דווקא באירוע בשם OnSetEditText. הסיבה לכך פשוטה. אני רוצה שבזמן הקביעה מה הוא העריכה, אני אחליט אם זה תקין או לא:

procedure TForm1.sgGraphDetailsSetEditText(Sender: TObject; ACol, ARow: Integer;
  const Value: string);
var num : double;
begin
  if (ACol = 2) and (Value  '') then
    begin
      if not TryStrToFloat(Value, num) then // do we have a real floating point number ?
        begin
          sgGraphDetails.Cells[ACol, ARow] := '';
        end;
    end;
end;

כאן אני מנסה להמיר בזמן העריכה את הערך שהתקבל. במידה והוא מתאים למספר עשרוני, אני לא נוגע בתוכן, אבל במידה והוא לא, אז אני הופך את התא לריק.
אם נרצה ליצור תוכנה מלאה, ולא רק הדגמה, אבדוק כאן כי העמודה של הצבעים גם מכילה טקסט תקין עבור צבע. אך במקרה הזה, החלטתי שלא להוסיף לכך קוד.

בחלק הבא (כאמור), אציג כיצד להגיע תאכלס ליצירת הגרף.

TAChart – חלק שני

בחלק הקודם, דיברתי על קצה המזלג אודות TAChart. בשל אורך הפוסט, הוא חולק למספר חלקים, וסה"כ יהיו 4 חלקים לכל הנושא (כולל הפוסט הקודם), בשביל להקל על הקריאה.

tachart_example

חשבתי להתחיל לפשט דברים, אז בחרתי להציג גרף מסוג פאי (גם הייתי קצת רעב, אני חייב להודות).

במקום ללמד אתכם לתכנת רק וויזואלית (הכוח של לזרוס), החלטתי לשלב בין השניים. הגדרות מאוד בסיסיות מוגדרות בצורה גרפית, כל השאר בקוד. בחלק הזה, אתמקד בחלק הוויזואלי בתכנות. החלקים הבאים יתמקדו בקוד עצמו.

חשוב להדגיש כי כל מה שיצרתי בצורה וויזואלית, ניתן לבצע דרך קוד, ומרבית הדברים שכתבתי בקוד (אך לא כולם), יכולים להתבצע גם בצורה וויזואלית.

עיצוב וויזואלי

דבר ראשון, ניצור לנו אפליקציה חדשה עם לזרוס. נלך לטאב של Standard אשר סבור להניח כי כבר מצביע לכם על דברים, נזרוק על הטופס TPanel, ונגיד לו כי Align הוא Bottom. זה אומר לרכיב שתמיד ידאג להצמיד את עצמו לתחתית הcontiner שלו, במקרה הזה כמובן, זה החלון שלנו.

הרכיב קיבל את השם Panel1. אני שיניתי לו את השם ל pnlBottom, בשביל לתאר את התפקיד שלו. עבורי לפחות זה אומר שהוא מכסה את האיזור התחתון רק כ container.  סוג של דרך שמות שהרגלתי את עצמי לתת לתפקיד שכזה.

לאחר מכן, נלך לטאב של Additional ונזרוק לנו על ה pnlBottom את הרכיב TStringGrid. זה בעצם הרכיב שאיתו נבצע את העריכות שלנו.

גם לרכיב זה, שיניתי את השם, וגרמתי לו להיות sgGraphDetails. המקדם מסביר כי זה StringGrid, בעוד שהשם מסביר לי מה הוא עושה.

נזרוק 4 כפתורים (תבחרו את הסוג שלדעתכם מתאים) אל pnlBottom , ונתחיל לשחק עם העיצוב שנרצה לקבל.

אני למשל בחרתי כי הכפתורים יהיו בצד ימים, ומסודרים לפי סוגי פעולות. כאשר ה2 העליונים תמיד דבוקים כלפי מעלה, והשניים התחתונים כלפי מטה, והם גם תמיד דבוקים לצד ימין (כל הארבעה). מבצעים זאת על ידי שימוש בתכונה Anchors (ראו את התמונה למעלה).

  • הכפתור הראשון קיבל כותרת של Add Item. והוא קיבל את השם btnAddItem.
  • הכפתור השני קיבל את השם Remove Last Item .השם אותו קיבל הוא btnRemoveLastItem.
  • הכפתור השלישי קיבל כותרת של Apply. והשם שלו הוא btnApply.
  • הכפתור הרביעי קיבל כותרת של Export. וכמובן שהשם שלו כמו שאתם כבר מזמן, מבינים הוא btnExport.

לאחר מכן, היה קל יותר למקם את sgGraphDetails. אותו מיקמתי להיות צמוד גם לימין, גם לשמאל, גם למעלה וגם למטה, וברוחב שתמיד לא יתנגש עם הכפתורים. עושים זאת קודם כל על ידי שינוי הגדלים בצורה חופשית, ואז משתמשים שוב בAnchors על מנת להשיג זאת.

אמרתי לsgGraphDetails, שיש לו רק שורה אחת כרגע  על ידי שינוי התכונה RowCount.
לאחר מכן בתכונה Options, הודעתי כי האפשרות לעריכה מאופשרת.
עם ה StringGrid, הלכתי להגדיר את תכונת ה Columns בצורה וויזואלית.

  • העמודה הראשונה שהגדרתי קיבלה כותרת בשם Name. וזהו השינוי היחיד שהיא קיבלה.
  • העמודה השניה שהגדרתי קיבלה כותרת בשם Percentage וגם כאן זה השינוי היחיד.
  • העמודה השלישית, קיבלה את הכותרת Color, אבל קיבלה עוד שינוי: ButtonStyle מצביע על כפתור בעל שלוש נקודות (Ellipsis), היות ואנחנו נאפשר למשתמש לבחור בצורה וויזואלית איזה צבע הוא מעוניין להשתמש עבור כל עמודה לגרף.

לאחר מכן, זרקתי על הטופס, רכיב בשם TSplitter. כיוונתי אותו באמצעות align להיות צמוד לBottom. הוא יאפשר לנו לשנות את גודל הTPanel וכן של הגרף בצורה דינאמית. הרכיב צריך להיות מעל pnlBottom.
הSplitter קיבל את השם spltBottom.

עכשיו הלכתי לטאב הנקרא Chart וזרקתי על החלון רכיב בשם TAChart, והגדרתי אותו עם Align להיות על הclient, דבר שאומר כי הוא תופס את כל הגודל הפנוי האפשרי.

שיחקתי עם הגדרות ה Legend של Chart (הייתי מאוד מקורי בשם שלו, תודו) שיתאימו לצורך ולמראה שאני רוצה, וכן שיניתי את הוויזואליות של הצירים, וצבע הרקעים השונים, וזה כל השינויים שעשיתי וויזואלית.

זרקתי גם מטאב Dialogs שני רכיבים. זרקתי את TColorDialog לבחירת צבע, וכן SaveDialog, לייצא יותר מאוחר את הגרף.

tachart_designtime

TAChart – חלק ראשון

להכיר על TAChart על קצה המזלג

TAChart הוא למעשה סדרה של רכיבים עם המון כוח ועצמה בלזרוס. הסדרה של הרכיבים מאפשרת לנו ליצור גרפים ממספר מקורות שאנחנו בוחרים כגון הזנה עצמית, מידע "hard coded", הזנה ממסד נתונים וכו' …

tachart browser statistics

אבל זה אפילו לא מתחיל לתאר את הרכיבים. הרעיון של הרכיבים הוא לאפשר גמישות ליצור איזה סוג גרף העולה כצורך על המתכנת. הוא מבצע את זה על ידי הפרדה בין הצגת הגרף לבין מערכת חישוב הגרפים עצמה. ואם זה לא מספיק, הוא מאפשר ליצור עוד סוגי גרפים כרכיבים או תוספות משל עצמנו, כולל אפשרות של "ציור עצמי".
ניתן גם להוסיף מספר גרפים למערכת הציור בו זמנית, ולא להסתפק רק בגרף בודד בכל פעם.

על זה, אנחנו מוסיפים את היכולות המדהימות שלו לעבוד גם בצורה לא גרפית, כלומר אני יכול ליצור מערכת גרפים שלמה באתר לדוגמה, ולשמור כתמונה. אני יכול לעצב כל אלמנט במערכת הזו, ואפילו ליצור תמונה של "זום" רק על נקודות מדוייקות שאני רוצה להציג, במקום את כל הגרף.

הרכיבים יודעים גם להיכנס למערכות של דו"חות כדוגמת LazReport ובכך גם להתאים את עצמה לדו"ח מודפס, PDF וכו'. למעשה את הרכיבים לא מעניין סוג "בד הציור" עליהם הם נמצאים, כך שאפשר למשל לעבוד איתם באמצעות OpenGL, מערכת BGRA או אפילו מערכת Agg. זו הסיבה שאפשר כאמור ליצור מהם SVG בנוסף לתמונות Bitmap,  PDF וכו' ….
אבל זה לא הכל. ניתן גם להציג את הגרפים כיום בצורת אנימציה ובכך גם להמחיז את השינויים השונים, ולא לקבל אותם רק בצורה "יבשה".

הרכיבים ממשיכים להיות בפיתוח מתמיד כבר מספר שנים, ומאוד מומלץ לקחת אותם לסיבוב. מבטיח כי לא תתאכזבו מהתוצאות.

בחלק הבא, אציג כיצד יצרתי את התמונה למעלה, ואיך ליצור קוד אשר יבצע אותה בפועל.

Display Quote ההמשך

עברו כבר 10 חודשים מאז שהפסקתי לעבוד על Display Quotes, אבל לאחרונה בגלל מספר סיבות, חזרתי לפרוייקט כסוג של מנוחה ורגיעה מסויימת.

הדבר הראשון שעשיתי, היה להוסיף רישיון לפרוייקט בצורה רשמית. הוא כרגע משוחרר ברישיון MIT. מבחינתי תעשו מה שאתם רוצים עם מה שיצרתי. אם זה לימוד, שימוש כתוכנה, או כל דבר אחר העולה על רוחכם. אני עושה את זה כתחביב נטו.

display_quote_navigation_mode

החלטתי עכשיו לשים לעצמי 2 מטרות לגרסה שאני יוצר:

  1. ליצור תמיכה בהוספה, עריכה, מחיקה ושמירה של ציטוטים באמצעות הממשק
  2. אפשרות לפרסם לפייסבוק את הציטוט שעומד מולכם.

הבעיה עם פייסבוק, היא שאסור לי לפרסם את הסיסמה שהפרוייקט קיבל, ובנוסף אני צריך ליצור או להתחבר למימוש של OAuth2, אשר שונה מ OAuth1 למשל …

הבעיה עם פייסבוק קצת מונעת מתוכנת קוד פתוח לפתוח את הקוד עד הסוף. אני פשוט יצרתי 2 קבצים. קובץ אחד שמכיל את ההגדרות האמיתיות, והוא לא נמצא ב git. הוא מכיל רק את מזהה התוכנה והסיסמה שלה, ככה שלעקוב אחרי זה עם git לא נותן הרבה.

קובץ שני, הוא אותו קובץ, רק בלי המידע, ואתם תוכלו להשתמש בו במידה ותרצו לקחת את התוכנה ולגרום לה לעבוד עם פייסבוק. רק תהיו צריכים לרשום אותה בעצמכם קודם …

ההתחלה שלי היא קודם על העריכה,  היות ואני חושב שזה החלק הפשוט יותר, ומכניס אותי חזרה לקוד שלא נגעתי בו הרבה זמן.

אבל אז מאיר ציין משהו חשוב: הממשק יהיה עמוס אם אוסיף עוד רכיבים אליו. אז חשבתי על פתרון שבו המיקום של פקדי הניווט משתנה לפקדי העריכה. היות ואין היגיון גם לניווט להיות פעיל בזמן עריכה, אני גם עושה לפעולות האלו disable.

display_quote_edit_mode

עכשיו כאשר אני חושב על זה, אני לא יודע כל כך איפה להכניס למשל את הפקד של פייסבוק (בעתיד ארצה גם לפרסם אולי לעוד רשתות חברתיות, כמו Google+‎ למשל), אבל הרעיון להחליף את הפקדים, למעשה עוזר כאן, אז במקום ליצור משהו בינארי (מאחורי הקלעים), אני בעצם שומר "מצבים" של התצוגה. כרגע היות ויש שניים, זה מוצג וויזואלית כפעולה בינארית, אבל אין זה המצב בצורה שאני מתנהג בפועל.

לאחר שאסיים את 2 השלבים האלו, כנראה שהשלבים הבאים יהיו:

  • ניסיון לאתר כפילויות – מימוש אלגוריתמים שונים לזיהוי טקסט במבנה דומה אבל לא זהה (התחלה של מנוע חיפוש ?)
  • מימוש לתמיכה של שורת פקודה. כלומר להפריד לוגיקה בין GUI לבין הצורך האמיתי, ולאפשר להציג את הציטוטים גם באמצעות שורת פקודה, שליחה לפייסבוק, ואולי גם כ pipe לתוכנות אחרות.

עוד רעיונות ממכם יתקבלו בברכה.

הקוד עצמו, ד"א כרגיל נמצא ב github.

Gtk3, GObject Introspection ו Free Pascal

קראתי פוסט מעניין על מצב ה binding של GTK3 בעולם הפסקל, וגיליתי משהו מאוד מעניין: הוא נעשה לגמרי ללא התערבות מתכנתים. זהו סוג של תרגום לפוסט.

ביצוע הBinding משתמש למעשה בפרויקט שקהילת GTK יצרה בשם GObject Introspection.
אם להסביר על רגל אחת את מהות הפרוייקט, אז הוא לוקח את ה API של פרוייקט GTK וממיר את המידע לקבצי XML אותם ניתן לקרוא בכל שפת תכנות.

אז מה שעשו אנשים בעולם הפסקל הוא ליצור מערכת שיודעת לתרגם את אותו קובץ XML אשר קיבל את הסיומת gir, וממירים אותו לקוד פסקל. הפרוייקט אשר ממיר לפסקל נקרא gir2pascal.

קובץ כזה יראה כך: להמשיך לקרוא

לזרוס 1.0

כמעט כמתיחה של אחד באפריל, נוצר לו ענף 1.0 עבור לזרוס בתחילת אותו יום. וזוהי נקודה מאוד חשובה בהיסטוריה של הפרוייקט. אך זו לא היתה מתיחה, ואתמול בלילה לזרוס 1.0 שוחררה לאוויר העולם.

אודות לזרוס

לזרוס 0.9.29 המשתמש ב Qt תחת לינוקס

לזרוס היא סביבת עבודה משולבת (IDE) אשר משוחררת כקוד פתוח ומאפשרת פיתוח מואץ למערכות גרפיות, וכן לכתיבת קוד מקור גם ללא צורך בתכנות גרפי. היא מתמקדת בפסקל מונחה עצמים (ואף כתובה בשפה), אך מאפשרת גם להוסיף תמיכה לשפות נוספות. המערכת בנויה בצורה של חבילות התקנה (מנהל חבילות מאוד דומה לרעיונות הקיימים בלינוקס) המאפיינות את התוכנות שלה, התמיכות שלה בדברים וכיוב'… השימוש בחבילות מאפשרת להוסיף, ואף לשנות את היעוד שלה.

המערכת מאפשרת לפתח יישומים למגוון רחב של פלטפורמות, וסביבות גרפיות, לרוב ללא שינוי הקוד. היא עושה זאת על ידי שימוש בספריות פיתוח אשר מספקות כלים גבוהים יותר במקום להתמודד עם סביבה מסויימת. זו הסיבה שסיסמת הפרוייקט היא write once compile everywhere.

סביבות העבודה אשר כיום לזרוס יודעת לאפשר עבודה מולם הם: MS Windows, Linux, FreeBSD, Solaris, Mac OS X, WinCE, Android, JVM, iOS ועוד מספר מערכות אחרות, בהתאם לתמיכת המהדר.
בנוסף, ישנה תמיכה בסביבות גרפיות כדוגמת Windows GDI, X11, GTK, Qt, Cocoa, Carbon ו fpGUI.

התמיכה הזו מגיעה באמצעות ספריית רכיבים בשם LCL‎ ‏(Lazarus Component Library) אשר תפקידה הוא אספקת כלים להתמודדת עם כתיבת התוכנות הגרפיות (אך לא רק) ללא צורך בלימוד של סביבה מסויימת כדוגמת Windows GDI או Qt.

בנוסף, המערכת מגיעה עם תמיכה מובנת למספר מסדי נתונים בניהם ODBC, SQLite, Firebird SQL, MS SQL, Oracle, MySQL, PostgreSQL, Sybase ואפילו Paradox במידה והותקנו הספריות המתאימות במערכת. בנוסף גם יש תמיכה ל dBase בצורה טבעית.

ישנם תוספות רבות ללזרוס המספקות תמיכה ביותר מסדי נתונים, ואף במימוש שונה לאותם מסדי נתונים, אך הקוד שלך לא ישתנה בגלל שהחלפת מסד נתונים, או מנוע שכזה.

לזרוס אף מגיעה עם תמיכה ברירת מחדל לפיתוח מערכות CGI ברמה נמוכה מאוד בשם fpWeb ועוד מספר כלים אחרים כדוגמת ExtPascal המאפשר לכתוב תוכנת web וויזואלית שמומרת ל ExtJS.

כל זה הוא רק הקדמה בנושא, ויש עוד המון דברים שמקבלים עם סביבת הפיתוח עצמה. להמשיך לקרוא

שינוי תצורת ממשק ה IDE

גרסה 1.0 של לזרוס שהוכרזה בראשון לאפריל, לאט לאט מתקרבת לה, אבל תמיד עולה השאלה לגבי הממשק של לזרוס.עורך טקסט

ללזרוס יש יכולת לקבל "חבילות" (packages) אשר חלקן הן עבור תכנות בזמן ריצה, חלקן לזמן תכנון. אבל זה לא הכל. אפשר גם ליצור חבילה אשר משפיעה על הסביבה עצמה, ואפילו לשנות אותה.

באמצעות חבילה כזו, אפשר ליצור מצב של Dock לסביבת העבודה, אבל לאחרונה גיליתי עוד דרך מדהימה (לדעתי) שמשנה את סביבת העבודה בצורה הזו: KZDesktop.

תכנות גרפיהגישה של KZDesktop היא להשתמש ב Tabbed Based User Interface ולא בDock UI, SDI או MDI.

הרעיון הוא שכל הסביבה תהיה כאילו היא חלון אחד, רק היא משתנה בין הצרכים וה"חלונות" הפתוחים אצלה.

לצערי, העבודה הזו, לא תיכנס ללזרוס 1.0, אשר ממש מעבר לפינה. אולי הפיתוח יכנס לגרסה 1.2, או רק ישפיע על הפיתוח של לזרוס לכיוון בסגנון הזה, ימים אבל יגידו.

נכון לכתיבת פוסט זה, עדיין לא ניסיתי בעצמי את התוסף, אבל אנסה אותו בסופ"ש הזה וכנראה אדווח 🙂

התמונה הבאה, מציגה איך מתקינים חבילות בלזרוס, תכנות נעים 🙂

התקנת חבילות

פסקל ברברס

התארחתי בפודקאסט "רברס עם פלטפורמה", ודיברתי מעט על שפת פסקל מונחת עצמים, ובעיקר על FPC.

תודה לאורי ורן על האירוח.

אתם מוזמנים להקשיב , ובעיקר להעריך את העובדה שאני יותר כותב ופחות מדבר 🙂

כתיבת ממשקי משתמש בסיסיים ללא שימוש ב C או Glade

שלומי ישראלי הציג אתמול פוסט כיצד ניתן בקוד פתוח ליצור ממשקי משתמש בסיסיים באמצעות C ו Glade.

לדעתי האישית הצגות כאלו, רק מוכיחות לאנשים המתנגחים בקוד הפתוח כל מה שרע בקוד הפתוח, אז החלטתי להציג דרך בקוד פתוח נוחה, מהירה ונקיה יותר, ללא קשר אם ה toolkit שלנו הוא GTK, Qt, אנדרואיד או IOS. הכל אצלנו נשאר אותו הדבר. מה שמשתנה זו הצורה שאנחנו מהדרים את הקוד.

כל מה שאני מציג כאן בגישה גרפית, ניתן גם לעשות בקוד מקור, כולל טעינת המסכים שלנו מקובץ בזמן ריצה. רק אין באמת צורך בכך במרבית המקרים.

עבור תוכנה גרפית, נתחיל בכך שנעבוד עם Lazarus. ונתחיל שם פרוייקט חדש:

הממשק בנוי ממספר חלונות, אשר את חלקם אתם רואים בתמונה. והוא נועד לסייע לנו לכתוב תוכנות בצורה כמה שיותר פשוטה, נוחה וכמה שפחות מאמץ, וכמה שפחות חזרה על קוד. בנוסף, הוא בנוי להיות חוצה פלטפורמות או סביבות גרפיות, ובכך מציג לנו API אחיד עבור כל סוג ממשק, ולמעשה לא אכפת לנו אם אנחנו עובדים ב GTK או Qt. זה לא חשוב לנו. להמשיך לקרוא